From 5ffbdbc0274ea8fbffe114dda06599cdf36c6c26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Mat=C4=9Bj=C4=8Dek?= Date: Thu, 24 Nov 2022 23:45:17 +0100 Subject: [PATCH 01/12] Refactoring targetting IO leaks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Using try-with - Safer ZipEntry management, new closeable WritableArchiveEntry - Revisited FileUtils - deleted unused methods - added USER_HOME file - new ensureWritableDir method; if the directory cannot be used or created, throws ISE - ProprietaryReader.readFrom closes the input OR sets that to a returned object - The behavior is not much consistent and I don't like it, but now it is documented and better controlled. - Implementations are final to limit risks. - Fix: MIMEMessage is closeable! - Fix: JsonParser doesn't close the input if it is a stream! - AsadminSecurityUtil.GF_CLIENT_DIR constant - by default subdir in user's home as it was before this commit - can be reset by GF_CLIENT_DIR environment property. - MUST be writeable, client should crash otherwise. - ArchivistUtils deleted - duplicit to FileUtils Signed-off-by: David Matějček --- .../client/acc/ACCStartupContext.java | 11 +- .../server/core/AppClientDeployerHelper.java | 225 ++--- .../StandaloneAppClientDeployerHelper.java | 55 +- .../internal/api/ConnectorsUtil.java | 8 +- .../archivist/ApplicationArchivist.java | 28 +- .../deployment/archivist/Archivist.java | 77 +- .../archivist/ExtensionsArchivist.java | 12 +- .../javaee/core/deployment/DolProvider.java | 15 +- .../javaee/full/deployment/EarHandler.java | 19 +- .../admin/cli/remote/RemoteCommand.java | 4 +- .../enterprise/admin/launcher/GFLauncher.java | 63 +- .../admin/rest/resources/StatusGenerator.java | 6 +- .../admin/remote/RemoteAdminCommand.java | 160 ++-- .../admin/remote/RemoteResponseManager.java | 40 +- .../admin/remote/RemoteRestAdminCommand.java | 61 +- .../ActionReportJsonProprietaryReader.java | 19 +- ...dminCommandStateJsonProprietaryReader.java | 14 +- .../reader/MultipartProprietaryReader.java | 87 +- ...aramsWithPayloadJsonProprietaryReader.java | 4 +- ...rogressStatusDTOJsonProprietaryReader.java | 14 +- ...gressStatusEventJsonProprietaryReader.java | 15 +- .../remote/reader/ProprietaryReader.java | 17 +- .../reader/StringProprietaryReader.java | 19 +- .../util/cache/ByteArrayDataProvider.java | 5 +- .../admin/util/cache/StringDataProvider.java | 2 +- .../admin/cluster/CreateNodeSshCommand.java | 32 +- .../v3/admin/cluster/NodeUtils.java | 8 +- .../cluster/SecureAdminBootstrapHelper.java | 11 +- .../v3/admin/cluster/SetupSshCommand.java | 69 +- .../cli/cluster/InstallNodeSshCommand.java | 29 +- .../cli/cluster/NativeRemoteCommandsBase.java | 44 +- .../admin/cli/cluster/SetupSshKey.java | 90 +- .../cluster/SynchronizeInstanceCommand.java | 23 +- .../cli/cluster/UninstallNodeSshCommand.java | 67 +- .../cluster/ssh/launcher/SSHLauncher.java | 292 +++--- .../glassfish/cluster/ssh/util/SSHUtil.java | 143 ++- .../glassfish/admin/amx/util/AMXDebug.java | 11 +- .../enterprise/universal/io/SmartFile.java | 60 +- .../com/sun/enterprise/util/CULoggerInfo.java | 44 +- .../com/sun/enterprise/util/io/FileUtils.java | 888 +++++------------- .../util/io/LocalStrings.properties | 1 - .../util/shared/ArchivistUtils.java | 62 -- .../com/sun/enterprise/util/zip/ZipFile.java | 32 +- .../admin/payload/PayloadFilesManager.java | 27 +- .../sun/enterprise/util/io/FileUtilsTest.java | 72 +- .../common-util/src/test/resources/empty.txt | 0 .../src/test/resources/simplestring.txt | 1 - .../src/test/resources/v2domain.xml | 224 ----- .../src/test/resources/verysimplestring.txt | 1 - .../deployment/archive/WritableArchive.java | 17 +- .../archive/WritableArchiveEntry.java | 73 ++ .../internal/deployment/GenericHandler.java | 84 +- .../enterprise/v3/admin/CheckpointHelper.java | 16 +- .../v3/server/ApplicationLifecycle.java | 118 ++- .../v3/server/ApplicationLoaderService.java | 49 +- .../enterprise/v3/server/UpgradeStartup.java | 224 ++--- .../admin/InstanceDeployCommand.java | 17 +- .../deploy/shared/ArchiveFactory.java | 7 +- .../enterprise/deploy/shared/FileArchive.java | 76 +- .../deploy/shared/MemoryMappedArchive.java | 88 +- .../deploy/shared/OutputJarArchive.java | 44 +- .../deployment/common/ClientJarWriter.java | 88 +- .../deployment/common/DeploymentUtils.java | 24 +- .../deployment/common/ModuleExploder.java | 6 +- .../deploy/shared/FileArchiveTest.java | 36 +- .../osgicontainer/OSGiArchiveHandler.java | 122 +-- .../sun/enterprise/security/common/Util.java | 43 +- .../embedded/EmbeddedSecurityUtil.java | 5 +- 68 files changed, 1751 insertions(+), 2597 deletions(-) delete mode 100644 nucleus/common/common-util/src/main/java/com/sun/enterprise/util/shared/ArchivistUtils.java delete mode 100644 nucleus/common/common-util/src/test/resources/empty.txt delete mode 100644 nucleus/common/common-util/src/test/resources/simplestring.txt delete mode 100644 nucleus/common/common-util/src/test/resources/v2domain.xml delete mode 100644 nucleus/common/common-util/src/test/resources/verysimplestring.txt create mode 100644 nucleus/common/glassfish-api/src/main/java/org/glassfish/api/deployment/archive/WritableArchiveEntry.java diff --git a/appserver/appclient/client/acc/src/main/java/org/glassfish/appclient/client/acc/ACCStartupContext.java b/appserver/appclient/client/acc/src/main/java/org/glassfish/appclient/client/acc/ACCStartupContext.java index 1a5970f679e..335a98c800f 100644 --- a/appserver/appclient/client/acc/src/main/java/org/glassfish/appclient/client/acc/ACCStartupContext.java +++ b/appserver/appclient/client/acc/src/main/java/org/glassfish/appclient/client/acc/ACCStartupContext.java @@ -1,4 +1,5 @@ /* + * Copyright (c) 2022 Contributors to the Eclipse Foundation * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the @@ -18,6 +19,8 @@ import com.sun.enterprise.glassfish.bootstrap.MainHelper; import com.sun.enterprise.module.bootstrap.StartupContext; +import com.sun.enterprise.util.io.FileUtils; + import java.io.File; import java.net.URI; import java.net.URISyntaxException; @@ -70,11 +73,9 @@ private static File getRootDirectory() { throw new RuntimeException(ex); } if (jarURI.getScheme().startsWith("http")) { - /* - * We do not really rely on the root directory during Java - * Web Start launches but we must return something. - */ - return new File(System.getProperty("user.home")); + // We do not really rely on the root directory during Java + // Web Start launches but we must return something. + return FileUtils.USER_HOME; } File jarFile = new File(jarURI); File dirFile = jarFile.getParentFile().getParentFile(); diff --git a/appserver/appclient/server/core/src/main/java/org/glassfish/appclient/server/core/AppClientDeployerHelper.java b/appserver/appclient/server/core/src/main/java/org/glassfish/appclient/server/core/AppClientDeployerHelper.java index bbf60cd68d2..7791227997a 100644 --- a/appserver/appclient/server/core/src/main/java/org/glassfish/appclient/server/core/AppClientDeployerHelper.java +++ b/appserver/appclient/server/core/src/main/java/org/glassfish/appclient/server/core/AppClientDeployerHelper.java @@ -1,4 +1,5 @@ /* + * Copyright (c) 2022 Contributors to the Eclipse Foundation * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the @@ -16,6 +17,13 @@ package org.glassfish.appclient.server.core; +import com.sun.enterprise.deploy.shared.FileArchive; +import com.sun.enterprise.deployment.Application; +import com.sun.enterprise.deployment.ApplicationClientDescriptor; +import com.sun.enterprise.deployment.archivist.AppClientArchivist; +import com.sun.enterprise.deployment.deploy.shared.OutputJarArchive; +import com.sun.enterprise.util.io.FileUtils; + import java.io.File; import java.io.IOException; import java.io.InputStream; @@ -40,6 +48,7 @@ import org.glassfish.api.deployment.DeploymentContext; import org.glassfish.api.deployment.archive.ReadableArchive; import org.glassfish.api.deployment.archive.WritableArchive; +import org.glassfish.api.deployment.archive.WritableArchiveEntry; import org.glassfish.appclient.server.core.jws.JavaWebStartInfo; import org.glassfish.appclient.server.core.jws.servedcontent.ASJarSigner; import org.glassfish.appclient.server.core.jws.servedcontent.DynamicContent; @@ -53,13 +62,6 @@ import org.glassfish.hk2.api.ServiceLocator; import org.glassfish.internal.api.ServerContext; -import com.sun.enterprise.deploy.shared.FileArchive; -import com.sun.enterprise.deployment.Application; -import com.sun.enterprise.deployment.ApplicationClientDescriptor; -import com.sun.enterprise.deployment.archivist.AppClientArchivist; -import com.sun.enterprise.deployment.deploy.shared.OutputJarArchive; -import com.sun.enterprise.util.shared.ArchivistUtils; - /** * Encapsulates the details of generating the required JAR file(s), * depending on whether the app client is stand-alone or is nested @@ -86,7 +88,7 @@ public abstract class AppClientDeployerHelper { private final String appName; private final String clientName; - private JarFile gfClientModuleJarFile; + private final JarFile gfClientModuleJarFile; private final Application application; @@ -346,10 +348,10 @@ File JAROfExpandedSubmodule(final URI candidateSubmoduleURI) throws IOException * entries() method omits it. */ Manifest mf = source.getManifest(); - OutputStream os = target.putNextEntry(JarFile.MANIFEST_NAME); - mf.write(os); - target.closeEntry(); - copyArchive(source, target, Collections.EMPTY_SET); + try (OutputStream os = target.putNextEntry(JarFile.MANIFEST_NAME)) { + mf.write(os); + } + copyArchive(source, target, Collections.emptySet()); target.close(); return new File(target.getURI()); } @@ -484,127 +486,101 @@ protected void addClientPolicyFiles(final OutputJarArchive clientFacadeArchive) protected abstract void copyFileToTopLevelJAR(final OutputJarArchive clientFacadeArchive, final File f, final String path) throws IOException; protected final void generateAppClientFacade() throws IOException, URISyntaxException { - OutputJarArchive facadeArchive = new OutputJarArchive(); - /* - * Make sure the directory subtree to contain the facade exists. If the - * client URI within the EAR contains a directory then that directory - * probably does not exist in the generated dir for this app...not yet - * anyway...it is about to exist. - */ - final File facadeFile = new File(facadeServerURI(dc)); - if ( ! facadeFile.getParentFile().exists()) { - if ( ! facadeFile.getParentFile().mkdirs()) { - final String msg = logger.getResourceBundle().getString("enterprise.deployment.appclient.errormkdirs"); - throw new IOException(MessageFormat.format(msg, facadeFile.getAbsolutePath())); + try (OutputJarArchive facadeArchive = new OutputJarArchive()) { + /* + * Make sure the directory subtree to contain the facade exists. If the + * client URI within the EAR contains a directory then that directory + * probably does not exist in the generated dir for this app...not yet + * anyway...it is about to exist. + */ + final File facadeFile = new File(facadeServerURI(dc)); + if (!facadeFile.getParentFile().exists()) { + if (!facadeFile.getParentFile().mkdirs()) { + final String msg = logger.getResourceBundle() + .getString("enterprise.deployment.appclient.errormkdirs"); + throw new IOException(MessageFormat.format(msg, facadeFile.getAbsolutePath())); + } } - } - facadeArchive.create(facadeServerURI(dc)); - ReadableArchive source = dc.getSource(); - Manifest sourceManifest = source.getManifest(); - if (sourceManifest == null) { - final String msg = logger.getResourceBundle().getString("enterprise.deployment.appclient.noManifest"); - throw new IOException(MessageFormat.format(msg, source.getURI().toASCIIString())); - } - Manifest facadeManifest = facadeArchive.getManifest(); - initGeneratedManifest(sourceManifest, facadeManifest, - facadeClassPath(), PUScanTargets(), application); - /* - * If the developer's app client JAR contains a splash screen, copy - * it from the original JAR to the facade so the Java launcher can - * display it when the app client is launched. - */ - final Attributes srcMainAttrs = sourceManifest.getMainAttributes(); - if (srcMainAttrs == null) { - final String msg = logger.getResourceBundle().getString("enterprise.deployment.appclient.noMainAttrs"); - throw new IOException(MessageFormat.format(msg, source.getURI().toASCIIString())); - } - String splash = srcMainAttrs.getValue(AppClientDeployer.SPLASH_SCREEN_IMAGE); - if (splash != null) { - copy(source, facadeArchive, splash); - } - /* - * Write the manifest to the facade. - */ - OutputStream os = facadeArchive.putNextEntry(JarFile.MANIFEST_NAME); - facadeManifest.write(os); - facadeArchive.closeEntry(); - /* - * Write the updated descriptors to the facade. - */ - writeUpdatedDescriptors(source, facadeArchive, appClientDesc); - - /* - * Because of how persistence units are discovered and added to the - * app client DOL object when the archivist reads the descriptor file, - * add any META-INF/persistence.xml file from the developer's client - * to the client facade. (The generated descriptor and the - * persistence.xml files need to be in the same archive.) - */ - copyPersistenceUnitXML(source, facadeArchive); + facadeArchive.create(facadeServerURI(dc)); + ReadableArchive source = dc.getSource(); + Manifest sourceManifest = source.getManifest(); + if (sourceManifest == null) { + final String msg = logger.getResourceBundle().getString("enterprise.deployment.appclient.noManifest"); + throw new IOException(MessageFormat.format(msg, source.getURI().toASCIIString())); + } + Manifest facadeManifest = facadeArchive.getManifest(); + initGeneratedManifest(sourceManifest, facadeManifest, facadeClassPath(), PUScanTargets(), application); + /* + * If the developer's app client JAR contains a splash screen, copy + * it from the original JAR to the facade so the Java launcher can + * display it when the app client is launched. + */ + final Attributes srcMainAttrs = sourceManifest.getMainAttributes(); + if (srcMainAttrs == null) { + final String msg = logger.getResourceBundle().getString("enterprise.deployment.appclient.noMainAttrs"); + throw new IOException(MessageFormat.format(msg, source.getURI().toASCIIString())); + } + String splash = srcMainAttrs.getValue(AppClientDeployer.SPLASH_SCREEN_IMAGE); + if (splash != null) { + copy(source, facadeArchive, splash); + } + /* + * Write the manifest to the facade. + */ + try (OutputStream os = facadeArchive.putNextEntry(JarFile.MANIFEST_NAME)) { + facadeManifest.write(os); + } + /* + * Write the updated descriptors to the facade. + */ + writeUpdatedDescriptors(source, facadeArchive, appClientDesc); - copyMainClass(facadeArchive); + /* + * Because of how persistence units are discovered and added to the + * app client DOL object when the archivist reads the descriptor file, + * add any META-INF/persistence.xml file from the developer's client + * to the client facade. (The generated descriptor and the + * persistence.xml files need to be in the same archive.) + */ + copyPersistenceUnitXML(source, facadeArchive); - addTopLevelContentToClientFacade(facadeArchive); + copyMainClass(facadeArchive); - facadeArchive.close(); + addTopLevelContentToClientFacade(facadeArchive); + } } /** * copy the entryName element from the source abstract archive into * the target abstract archive */ - static void copy( - ReadableArchive source, WritableArchive target, String entryName) - throws IOException { - - InputStream is = null; - OutputStream os = null; - try { - is = source.getEntry(entryName); - if (is != null) { - try { - os = target.putNextEntry(entryName); - } catch (ZipException ze) { - // this is a duplicate... - return; - } - ArchivistUtils.copyWithoutClose(is, os); - } else { + static void copy(ReadableArchive source, WritableArchive target, String entryName) throws IOException { + try (InputStream is = source.getEntry(entryName)) { + if (is == null) { // This may be a directory specification if there is no entry // in the source for it...for example, a directory expression // in the Class-Path entry from a JAR's manifest. // // Try to copy all entries from the source that have the // entryName as a prefix. - for (Enumeration e = source.entries(entryName); e.hasMoreElements();) { - copy(source, target, (String) e.nextElement()); + for (Enumeration e = source.entries(entryName); e.hasMoreElements();) { + copy(source, target, e.nextElement()); } - } - } catch (IOException ioe) { - throw ioe; - } finally { - IOException closeEntryIOException = null; - if (os != null) { - try { - target.closeEntry(); - } catch (IOException ioe) { - closeEntryIOException = ioe; + } else { + try (WritableArchiveEntry os = target.putNextEntry(entryName)) { + FileUtils.copy(is, os); + } catch (ZipException ze) { + // this is a duplicate... + return; } } - if (is != null) { - is.close(); - } - - if (closeEntryIOException != null) { - throw closeEntryIOException; - } } } - static void copyArchive( - ReadableArchive source, WritableArchive target, Set excludeList) { - for (Enumeration e = source.entries(); e.hasMoreElements();) { - String entryName = String.class.cast(e.nextElement()); + + static void copyArchive(ReadableArchive source, WritableArchive target, Set excludeList) { + for (Enumeration e = source.entries(); e.hasMoreElements();) { + String entryName = e.nextElement(); if (excludeList.contains(entryName)) { continue; } @@ -616,16 +592,11 @@ static void copyArchive( } } - private void copyClass(final WritableArchive facadeArchive, - final String classResourcePath) throws IOException { - OutputStream os = facadeArchive.putNextEntry(classResourcePath); - InputStream is = openByteCodeStream(classResourcePath); - DeploymentUtils.copyStream(is, os); - try { - is.close(); - facadeArchive.closeEntry(); - } catch (IOException ignore) { + private void copyClass(final WritableArchive facadeArchive, final String classResourcePath) throws IOException { + try (InputStream is = openByteCodeStream(classResourcePath); + OutputStream os = facadeArchive.putNextEntry(classResourcePath)) { + DeploymentUtils.copyStream(is, os); } } @@ -636,14 +607,12 @@ private void copyMainClass(final WritableArchive facadeArchive) throws IOExcepti private void copyPersistenceUnitXML(final ReadableArchive sourceClient, final WritableArchive facadeArchive) throws IOException { - InputStream persistenceXMLStream = sourceClient.getEntry(PERSISTENCE_XML_PATH); - if (persistenceXMLStream != null) { - OutputStream os = facadeArchive.putNextEntry(PERSISTENCE_XML_PATH); - DeploymentUtils.copyStream(persistenceXMLStream, os); - try { - persistenceXMLStream.close(); - facadeArchive.closeEntry(); - } catch (IOException ignore) { + try (InputStream persistenceXMLStream = sourceClient.getEntry(PERSISTENCE_XML_PATH)) { + if (persistenceXMLStream == null) { + return; + } + try (OutputStream os = facadeArchive.putNextEntry(PERSISTENCE_XML_PATH)) { + DeploymentUtils.copyStream(persistenceXMLStream, os); } } } diff --git a/appserver/appclient/server/core/src/main/java/org/glassfish/appclient/server/core/StandaloneAppClientDeployerHelper.java b/appserver/appclient/server/core/src/main/java/org/glassfish/appclient/server/core/StandaloneAppClientDeployerHelper.java index 323a9155f88..a2a8940bac4 100644 --- a/appserver/appclient/server/core/src/main/java/org/glassfish/appclient/server/core/StandaloneAppClientDeployerHelper.java +++ b/appserver/appclient/server/core/src/main/java/org/glassfish/appclient/server/core/StandaloneAppClientDeployerHelper.java @@ -1,4 +1,5 @@ /* + * Copyright (c) 2022 Contributors to the Eclipse Foundation * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the @@ -19,9 +20,8 @@ import com.sun.enterprise.deployment.Application; import com.sun.enterprise.deployment.ApplicationClientDescriptor; import com.sun.enterprise.deployment.archivist.AppClientArchivist; -import com.sun.enterprise.deployment.deploy.shared.JarArchive; import com.sun.enterprise.deployment.deploy.shared.OutputJarArchive; -import com.sun.logging.LogDomains; + import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; @@ -38,6 +38,7 @@ import java.util.jar.Manifest; import java.util.logging.Level; import java.util.logging.Logger; + import org.glassfish.api.deployment.DeployCommandParameters; import org.glassfish.api.deployment.DeploymentContext; import org.glassfish.api.deployment.archive.ReadableArchive; @@ -138,20 +139,13 @@ protected void copyFileToTopLevelJAR(final OutputJarArchive clientFacadeArchive, } private void copyToArchive(final File inputFile, final OutputJarArchive outputArchive, final String pathInJar) throws IOException { - final OutputStream os = outputArchive.putNextEntry(pathInJar); - final InputStream is = new BufferedInputStream(new FileInputStream(inputFile)); - final byte[] buffer = new byte[512]; - int bytesRead; - try { + try (OutputStream os = outputArchive.putNextEntry(pathInJar); + InputStream is = new BufferedInputStream(new FileInputStream(inputFile))) { + final byte[] buffer = new byte[512]; + int bytesRead; while ((bytesRead = is.read(buffer)) != -1) { os.write(buffer, 0, bytesRead); } - } finally { - try { - os.flush(); - } finally { - is.close(); - } } } @@ -292,7 +286,7 @@ protected Set clientLevelDownloads() throws IOException { * 1. the original app client JAR, * 2. the facade JAR */ - Set downloads = new HashSet(); + Set downloads = new HashSet<>(); downloads.add(new Artifacts.FullAndPartURIs( appClientServerURI(dc()), appClientUserURI(dc()))); @@ -337,28 +331,25 @@ protected String facadeClassPath() { return appClientUserURI(dc()).toASCIIString(); } protected void copyOriginalAppClientJAR(final DeploymentContext dc) throws IOException { - ReadableArchive originalSource = ((ExtendedDeploymentContext) dc).getOriginalSource(); - originalSource.open(originalSource.getURI()); - OutputJarArchive target = new OutputJarArchive(); - target.create(appClientServerURI(dc)); - /* - * Copy the manifest explicitly because ReadableArchive.entries() - * excludes the manifest. - */ - Manifest originalManifest = originalSource.getManifest(); - OutputStream os = target.putNextEntry(JarFile.MANIFEST_NAME); - originalManifest.write(os); - target.closeEntry(); - copyArchive(originalSource, target, Collections.EMPTY_SET); - target.close(); - originalSource.close(); + try (ReadableArchive originalSource = ((ExtendedDeploymentContext) dc).getOriginalSource()) { + originalSource.open(originalSource.getURI()); + try (OutputJarArchive target = new OutputJarArchive()) { + target.create(appClientServerURI(dc)); + /* + * Copy the manifest explicitly because ReadableArchive.entries() + * excludes the manifest. + */ + Manifest originalManifest = originalSource.getManifest(); + try (OutputStream os = target.putNextEntry(JarFile.MANIFEST_NAME)) { + originalManifest.write(os); + } + copyArchive(originalSource, target, Collections.EMPTY_SET); + } + } } @Override protected String PUScanTargets() { return null; } - - - } diff --git a/appserver/connectors/connectors-internal-api/src/main/java/com/sun/appserv/connectors/internal/api/ConnectorsUtil.java b/appserver/connectors/connectors-internal-api/src/main/java/com/sun/appserv/connectors/internal/api/ConnectorsUtil.java index 0cb137e3fa1..43b77148f98 100644 --- a/appserver/connectors/connectors-internal-api/src/main/java/com/sun/appserv/connectors/internal/api/ConnectorsUtil.java +++ b/appserver/connectors/connectors-internal-api/src/main/java/com/sun/appserv/connectors/internal/api/ConnectorsUtil.java @@ -35,7 +35,6 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; -import java.io.OutputStream; import java.net.URI; import java.net.URISyntaxException; import java.net.URL; @@ -59,6 +58,7 @@ import org.glassfish.api.admin.config.ApplicationName; import org.glassfish.api.deployment.DeploymentContext; import org.glassfish.api.deployment.archive.ReadableArchive; +import org.glassfish.api.deployment.archive.WritableArchiveEntry; import org.glassfish.api.naming.SimpleJndiName; import org.glassfish.connectors.config.AdminObjectResource; import org.glassfish.connectors.config.ConnectorConnectionPool; @@ -818,9 +818,9 @@ public static boolean extractRar(String fileName, String rarName, String destDir LOG.log(Level.INFO, "could not find RAR [ " + rarName + " ] in the archive, skipping .rar extraction"); return false; } - try (FileArchive fa = new FileArchive(); OutputStream os = fa.putNextEntry(fileName)) { - FileUtils.copy(is, os, 0); - fa.closeEntry(); + try (FileArchive fa = new FileArchive(); + WritableArchiveEntry os = fa.putNextEntry(fileName)) { + FileUtils.copy(is, os); } catch (IOException e) { LOG.log(Level.SEVERE, "Exception while extracting RAR " + rarName + " from archive " + fileName, e); return false; diff --git a/appserver/deployment/dol/src/main/java/com/sun/enterprise/deployment/archivist/ApplicationArchivist.java b/appserver/deployment/dol/src/main/java/com/sun/enterprise/deployment/archivist/ApplicationArchivist.java index d379dcec87b..511eebe9f74 100644 --- a/appserver/deployment/dol/src/main/java/com/sun/enterprise/deployment/archivist/ApplicationArchivist.java +++ b/appserver/deployment/dol/src/main/java/com/sun/enterprise/deployment/archivist/ApplicationArchivist.java @@ -32,14 +32,11 @@ import com.sun.enterprise.deployment.util.DOLUtils; import com.sun.enterprise.util.LocalStringManagerImpl; import com.sun.enterprise.util.io.FileUtils; -import com.sun.enterprise.util.shared.ArchivistUtils; import jakarta.inject.Inject; import jakarta.inject.Provider; -import java.io.BufferedOutputStream; import java.io.File; -import java.io.FileOutputStream; import java.io.FilenameFilter; import java.io.IOException; import java.io.InputStream; @@ -122,50 +119,41 @@ protected void writeContents(ReadableArchive in, WritableArchive out) throws IOE Archivist subArchivist = archivistFactory.get().getArchivist(aModule.getModuleType()); subArchivist.initializeContext(this); subArchivist.setModuleDescriptor(aModule); + String archiveUri = aModule.getArchiveUri(); if (DOLUtils.getDefaultLogger().isLoggable(Level.FINE)) { - DOLUtils.getDefaultLogger().fine("Write " + aModule.getArchiveUri() + " with " + subArchivist); + DOLUtils.getDefaultLogger().fine("Write " + archiveUri + " with " + subArchivist); } // Create a new jar file inside the application .ear - WritableArchive internalJar = out.createSubArchive(aModule.getArchiveUri()); + final WritableArchive internalJar = out.createSubArchive(archiveUri); // we need to copy the old archive to a temp file so // the save method can copy its original contents from - File tmpFile = null; - BufferedOutputStream bos = null; - try (InputStream is = in.getEntry(aModule.getArchiveUri())) { + try (InputStream is = in.getEntry(archiveUri)) { if (in instanceof WritableArchive) { subArchivist.setArchiveUri(internalJar.getURI().getSchemeSpecificPart()); } else { tmpFile = getTempFile(path); - bos = new BufferedOutputStream(new FileOutputStream(tmpFile)); - ArchivistUtils.copy(is, bos); + FileUtils.copy(is, tmpFile, in.getEntrySize(archiveUri)); // configure archivist subArchivist.setArchiveUri(tmpFile.getAbsolutePath()); } subArchivist.writeContents(internalJar); - out.closeEntry(internalJar); } finally { + out.closeEntry(internalJar); if (tmpFile != null) { boolean ok = tmpFile.delete(); if (!ok) { logger.log(Level.WARNING, localStrings.getLocalString("enterprise.deployment.cantDelete", - "Error deleting file {0}", new Object[] {tmpFile.getAbsolutePath()})); - } - } - if (bos != null) { - try { - bos.close(); - } catch (IOException ioe) { - // ignore + "Error deleting file {0}", tmpFile)); } } } // no need to copy the bundle from the original jar file - filesToSkip.add(aModule.getArchiveUri()); + filesToSkip.add(archiveUri); } // now write the old contents and new descriptors diff --git a/appserver/deployment/dol/src/main/java/com/sun/enterprise/deployment/archivist/Archivist.java b/appserver/deployment/dol/src/main/java/com/sun/enterprise/deployment/archivist/Archivist.java index 16e23269bb5..806b8d1a8c7 100644 --- a/appserver/deployment/dol/src/main/java/com/sun/enterprise/deployment/archivist/Archivist.java +++ b/appserver/deployment/dol/src/main/java/com/sun/enterprise/deployment/archivist/Archivist.java @@ -30,7 +30,6 @@ import com.sun.enterprise.deployment.util.TracerVisitor; import com.sun.enterprise.util.LocalStringManagerImpl; import com.sun.enterprise.util.io.FileUtils; -import com.sun.enterprise.util.shared.ArchivistUtils; import jakarta.inject.Inject; @@ -69,6 +68,7 @@ import org.glassfish.api.deployment.archive.ArchiveType; import org.glassfish.api.deployment.archive.ReadableArchive; import org.glassfish.api.deployment.archive.WritableArchive; +import org.glassfish.api.deployment.archive.WritableArchiveEntry; import org.glassfish.deployment.common.DeploymentProperties; import org.glassfish.deployment.common.Descriptor; import org.glassfish.deployment.common.DescriptorVisitor; @@ -829,9 +829,9 @@ protected void writeContents(ReadableArchive in, WritableArchive out, Set if (overwriteManifest) { Manifest m = source.getManifest(); if (m != null) { - OutputStream os = target.putNextEntry(JarFile.MANIFEST_NAME); - m.write(os); - target.closeEntry(); + try (WritableArchiveEntry os = target.putNextEntry(JarFile.MANIFEST_NAME)) { + m.write(os); + } } } } @@ -1555,28 +1542,14 @@ public void copyInto(ReadableArchive source, WritableArchive target, Set // only copy the entry if the destination archive does not have this entry public void copyAnEntry(ReadableArchive in, WritableArchive out, String entryName) throws IOException { - InputStream is = null; - InputStream is2 = null; - ReadableArchive in2 = archiveFactory.openArchive(out.getURI()); - try { - is = in.getEntry(entryName); - is2 = in2.getEntry(entryName); + try (ReadableArchive in2 = archiveFactory.openArchive(out.getURI()); + InputStream is = in.getEntry(entryName); + InputStream is2 = in2.getEntry(entryName)) { if (is != null && is2 == null) { - OutputStream os = out.putNextEntry(entryName); - ArchivistUtils.copyWithoutClose(is, os); - } - } finally { - /* - *Close any streams that were opened. - */ - in2.close(); - if (is != null) { - is.close(); - } - if (is2 != null) { - is2.close(); + try (WritableArchiveEntry os = out.putNextEntry(entryName)) { + FileUtils.copy(is, os); + } } - out.closeEntry(); } } diff --git a/appserver/deployment/dol/src/main/java/com/sun/enterprise/deployment/archivist/ExtensionsArchivist.java b/appserver/deployment/dol/src/main/java/com/sun/enterprise/deployment/archivist/ExtensionsArchivist.java index 73ed19f1edd..cef4a40dde7 100644 --- a/appserver/deployment/dol/src/main/java/com/sun/enterprise/deployment/archivist/ExtensionsArchivist.java +++ b/appserver/deployment/dol/src/main/java/com/sun/enterprise/deployment/archivist/ExtensionsArchivist.java @@ -205,9 +205,9 @@ public void writeDeploymentDescriptors(Archivist main, BundleDescriptor descript public void writeStandardDeploymentDescriptors(Archivist main, BundleDescriptor descriptor, WritableArchive out) throws IOException { getStandardDDFile(descriptor).setArchiveType(main.getModuleType()); - OutputStream os = out.putNextEntry(standardDD.getDeploymentDescriptorPath()); - standardDD.write(descriptor, os); - out.closeEntry(); + try (OutputStream os = out.putNextEntry(standardDD.getDeploymentDescriptorPath())) { + standardDD.write(descriptor, os); + } } /** @@ -228,9 +228,9 @@ public void writeRuntimeDeploymentDescriptors(Archivist main, BundleDescriptor d } for (ConfigurationDeploymentDescriptorFile ddFile : confDDFilesToWrite) { ddFile.setArchiveType(main.getModuleType()); - OutputStream os = out.putNextEntry(ddFile.getDeploymentDescriptorPath()); - ddFile.write(descriptor, os); - out.closeEntry(); + try (OutputStream os = out.putNextEntry(ddFile.getDeploymentDescriptorPath())) { + ddFile.write(descriptor, os); + } } } diff --git a/appserver/deployment/jakartaee-core/src/main/java/org/glassfish/javaee/core/deployment/DolProvider.java b/appserver/deployment/jakartaee-core/src/main/java/org/glassfish/javaee/core/deployment/DolProvider.java index 11631ef9c9e..515ee0fac21 100644 --- a/appserver/deployment/jakartaee-core/src/main/java/org/glassfish/javaee/core/deployment/DolProvider.java +++ b/appserver/deployment/jakartaee-core/src/main/java/org/glassfish/javaee/core/deployment/DolProvider.java @@ -270,7 +270,6 @@ public String getNameFor(ReadableArchive archive, DeploymentContext context) { * @param archive the archive for the application */ public Application processDeploymentMetaData(ReadableArchive archive) throws Exception { - FileArchive expandedArchive = null; File tmpFile = null; ExtendedDeploymentContext context = null; Logger logger = Logger.getAnonymousLogger(); @@ -303,9 +302,10 @@ public Application processDeploymentMetaData(ReadableArchive archive) throws Exc if (!tmpDir.exists() && !tmpDir.mkdirs()) { throw new IOException("Unable to create directory " + tmpDir.getAbsolutePath()); } - expandedArchive = (FileArchive)archiveFactory.createArchive(tmpDir); - archiveHandler.expand(archive, expandedArchive, context); - context.setSource(expandedArchive); + try (FileArchive expandedArchive = (FileArchive)archiveFactory.createArchive(tmpDir)) { + archiveHandler.expand(archive, expandedArchive, context); + context.setSource(expandedArchive); + } } context.setPhase(DeploymentContextImpl.Phase.PREPARE); @@ -326,13 +326,6 @@ public Application processDeploymentMetaData(ReadableArchive archive) throws Exc if (context != null) { context.postDeployClean(true); } - if (expandedArchive != null) { - try { - expandedArchive.close(); - } catch (Exception e) { - // ignore - } - } if (tmpFile != null && tmpFile.exists()) { try { FileUtils.whack(tmpFile); diff --git a/appserver/deployment/jakartaee-full/src/main/java/org/glassfish/javaee/full/deployment/EarHandler.java b/appserver/deployment/jakartaee-full/src/main/java/org/glassfish/javaee/full/deployment/EarHandler.java index c33634579c0..a3d1c31ce1c 100644 --- a/appserver/deployment/jakartaee-full/src/main/java/org/glassfish/javaee/full/deployment/EarHandler.java +++ b/appserver/deployment/jakartaee-full/src/main/java/org/glassfish/javaee/full/deployment/EarHandler.java @@ -170,7 +170,6 @@ public void expand(ReadableArchive source, WritableArchive target, DeploymentCon for (ModuleDescriptor md : holder.app.getModules()) { String moduleUri = md.getArchiveUri(); ReadableArchive subArchive = null; - WritableArchive subTarget = null; ReadableArchive subArchiveToExpand = null; try { subArchive = source2.getSubArchive(moduleUri); @@ -185,8 +184,10 @@ public void expand(ReadableArchive source, WritableArchive target, DeploymentCon subHandler = deployment.getArchiveHandler(subArchive); } context.getModuleArchiveHandlers().put(moduleUri, subHandler); - if (subHandler != null) { - subTarget = target.createSubArchive(FileUtils.makeFriendlyFilenameExtension(moduleUri)); + if (subHandler == null) { + return; + } + try (WritableArchive subTarget = target.createSubArchive(FileUtils.makeFriendlyFilenameExtension(moduleUri))) { /* * A subarchive might be packaged as a subdirectory (instead of a nested JAR) in an EAR. If so and if it has the * same name as the directory into which we'll expand the submodule, make sure it is also of the correct archive @@ -204,16 +205,11 @@ public void expand(ReadableArchive source, WritableArchive target, DeploymentCon */ if (!areSameStorageType(subTarget, subArchive)) { final String msg = MessageFormat.format( - _logger.getResourceBundle().getString("enterprise.deployment.backend.badSubModPackaging"), - subArchive.getURI().toASCIIString(), subArchive.getClass().getName()); + _logger.getResourceBundle().getString("enterprise.deployment.backend.badSubModPackaging"), + subArchive.getURI().toASCIIString(), subArchive.getClass().getName()); throw new RuntimeException(msg); } } -// Keep the original submodule file because the app client deployer needs it. - /* - * // delete the original module file File origSubArchiveFile = new File( target.getURI().getSchemeSpecificPart(), - * moduleUri); origSubArchiveFile.delete(); - */ } } catch (IOException ioe) { _logger.log(Level.FINE, "Exception while processing " + moduleUri, ioe); @@ -222,9 +218,6 @@ public void expand(ReadableArchive source, WritableArchive target, DeploymentCon if (subArchive != null) { subArchive.close(); } - if (subTarget != null) { - subTarget.close(); - } if (subArchiveToExpand != null) { subArchiveToExpand.close(); } diff --git a/nucleus/admin/cli/src/main/java/com/sun/enterprise/admin/cli/remote/RemoteCommand.java b/nucleus/admin/cli/src/main/java/com/sun/enterprise/admin/cli/remote/RemoteCommand.java index 4bf487d138f..14ce5e0020e 100644 --- a/nucleus/admin/cli/src/main/java/com/sun/enterprise/admin/cli/remote/RemoteCommand.java +++ b/nucleus/admin/cli/src/main/java/com/sun/enterprise/admin/cli/remote/RemoteCommand.java @@ -101,8 +101,8 @@ private class CLIRemoteAdminCommand extends RemoteAdminCommand { * Construct a new remote command object. The command and arguments are supplied later using the execute method in the * superclass. */ - public CLIRemoteAdminCommand(String name, String host, int port, boolean secure, String user, char[] password, Logger logger, - String authToken) throws CommandException { + public CLIRemoteAdminCommand(String name, String host, int port, boolean secure, String user, char[] password, + Logger logger, String authToken) throws CommandException { super(name, host, port, secure, user, password, logger, getCommandScope(), authToken, true /* prohibitDirectoryUploads */); sessionCache = AsadminSecurityUtil.getGfClientSessionFile(host, port); } diff --git a/nucleus/admin/launcher/src/main/java/com/sun/enterprise/admin/launcher/GFLauncher.java b/nucleus/admin/launcher/src/main/java/com/sun/enterprise/admin/launcher/GFLauncher.java index 74a70a04742..86c4ec4873a 100644 --- a/nucleus/admin/launcher/src/main/java/com/sun/enterprise/admin/launcher/GFLauncher.java +++ b/nucleus/admin/launcher/src/main/java/com/sun/enterprise/admin/launcher/GFLauncher.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 Contributors to the Eclipse Foundation + * Copyright (c) 2022, 2024 Contributors to the Eclipse Foundation * Copyright (c) 2008, 2020 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the @@ -17,6 +17,32 @@ package com.sun.enterprise.admin.launcher; +import com.sun.enterprise.universal.glassfish.ASenvPropertyReader; +import com.sun.enterprise.universal.glassfish.GFLauncherUtils; +import com.sun.enterprise.universal.glassfish.TokenResolver; +import com.sun.enterprise.universal.i18n.LocalStringsImpl; +import com.sun.enterprise.universal.process.ProcessStreamDrainer; +import com.sun.enterprise.universal.xml.MiniXmlParser; +import com.sun.enterprise.universal.xml.MiniXmlParserException; +import com.sun.enterprise.util.OS; +import com.sun.enterprise.util.io.FileUtils; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.IOException; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Set; + import static com.sun.enterprise.admin.launcher.GFLauncher.LaunchType.fake; import static com.sun.enterprise.admin.launcher.GFLauncherConstants.DEFAULT_LOGFILE; import static com.sun.enterprise.admin.launcher.GFLauncherConstants.FLASHLIGHT_AGENT_NAME; @@ -36,37 +62,12 @@ import static com.sun.enterprise.util.SystemPropertyConstants.INSTALL_ROOT_PROPERTY; import static com.sun.enterprise.util.SystemPropertyConstants.INSTANCE_ROOT_PROPERTY; import static com.sun.enterprise.util.SystemPropertyConstants.JAVA_ROOT_PROPERTY; -import static com.sun.enterprise.util.io.FileUtils.copyFile; import static java.lang.Boolean.TRUE; import static java.util.Collections.emptyList; import static java.util.logging.Level.INFO; import static java.util.logging.Level.WARNING; import static java.util.stream.Collectors.toList; -import java.io.BufferedWriter; -import java.io.File; -import java.io.IOException; -import java.io.OutputStream; -import java.io.OutputStreamWriter; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Set; - -import com.sun.enterprise.universal.glassfish.ASenvPropertyReader; -import com.sun.enterprise.universal.glassfish.GFLauncherUtils; -import com.sun.enterprise.universal.glassfish.TokenResolver; -import com.sun.enterprise.universal.i18n.LocalStringsImpl; -import com.sun.enterprise.universal.process.ProcessStreamDrainer; -import com.sun.enterprise.universal.xml.MiniXmlParser; -import com.sun.enterprise.universal.xml.MiniXmlParserException; -import com.sun.enterprise.util.OS; -import com.sun.enterprise.util.io.FileUtils; - /** * This is the main Launcher class designed for external and internal usage. * @@ -943,17 +944,15 @@ private void setupUpgradeSecurity() throws GFLauncherException { if (callerParameters.isUpgrade() && domainXMLjvmOptions.sysProps.containsKey("java.security.manager")) { GFLauncherLogger.info(GFLauncherLogger.copy_server_policy); - - File source = new File(new File(new File(callerParameters.installDir, "lib"), "templates"), "server.policy"); - File target = new File(callerParameters.getConfigDir(), "server.policy"); - + Path source = callerParameters.installDir.toPath().resolve(Path.of("lib", "templates", "server.policy")); + Path target = callerParameters.getConfigDir().toPath().resolve("server.policy"); try { - copyFile(source, target); + Files.copy(source, target); } catch (IOException ioe) { // the actual error is wrapped differently depending on // whether the problem was with the source or target Throwable cause = ioe.getCause() == null ? ioe : ioe.getCause(); - throw new GFLauncherException(strings.get("copy_server_policy_error", cause.getMessage())); + throw new GFLauncherException(strings.get("copy_server_policy_error", cause.getMessage()), ioe); } } } diff --git a/nucleus/admin/rest/rest-service/src/main/java/org/glassfish/admin/rest/resources/StatusGenerator.java b/nucleus/admin/rest/rest-service/src/main/java/org/glassfish/admin/rest/resources/StatusGenerator.java index 70b825da7c9..a5a5e76f0ce 100644 --- a/nucleus/admin/rest/rest-service/src/main/java/org/glassfish/admin/rest/resources/StatusGenerator.java +++ b/nucleus/admin/rest/rest-service/src/main/java/org/glassfish/admin/rest/resources/StatusGenerator.java @@ -18,6 +18,7 @@ package org.glassfish.admin.rest.resources; import com.sun.enterprise.config.serverbeans.Domain; +import com.sun.enterprise.util.io.FileUtils; import jakarta.ws.rs.GET; import jakarta.ws.rs.Path; @@ -71,7 +72,8 @@ @Path("/status/") public class StatusGenerator extends AbstractResource { - private static final File FILE = new File(System.getProperty("user.home"), "GlassFishI18NData.properties"); + // FIXME: Wouldn't be better to send it to the client? + private static final File FILE = new File(FileUtils.USER_HOME, "GlassFishI18NData.properties"); private final Set commandsUsed = new TreeSet<>(); private final Set allCommands = new TreeSet<>(); @@ -162,7 +164,6 @@ public String getPlain() { status.append(entry.getKey()).append(" ::: ").append(entry.getValue()).append('\n'); } - // FIXME: Wouldn't be better to send it to the client? RestLogging.restLogger.log(Level.INFO, "Storing properties to the file {0}", FILE); try (FileOutputStream f = new FileOutputStream(FILE)) { propsI18N.store(f, ""); @@ -233,7 +234,6 @@ public String getHtml() { } status.append(""); - // FIXME: Wouldn't be better to send it to the client? RestLogging.restLogger.log(Level.INFO, "Storing properties to the file {0}", FILE); try (FileOutputStream f = new FileOutputStream(FILE)) { propsI18N.store(f, ""); diff --git a/nucleus/admin/util/src/main/java/com/sun/enterprise/admin/remote/RemoteAdminCommand.java b/nucleus/admin/util/src/main/java/com/sun/enterprise/admin/remote/RemoteAdminCommand.java index 816950644b1..fc7a5819863 100644 --- a/nucleus/admin/util/src/main/java/com/sun/enterprise/admin/remote/RemoteAdminCommand.java +++ b/nucleus/admin/util/src/main/java/com/sun/enterprise/admin/remote/RemoteAdminCommand.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 Contributors to the Eclipse Foundation + * Copyright (c) 2022, 2023 Contributors to the Eclipse Foundation * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the @@ -51,6 +51,7 @@ import java.net.URLEncoder; import java.net.UnknownHostException; import java.util.ArrayList; +import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.Locale; @@ -64,12 +65,12 @@ import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; +import org.glassfish.admin.payload.PayloadFilesManager; +import org.glassfish.admin.payload.PayloadImpl; import org.glassfish.api.admin.AuthenticationException; import org.glassfish.api.admin.CommandException; import org.glassfish.api.admin.CommandModel; import org.glassfish.api.admin.CommandModel.ParamModel; -import org.glassfish.admin.payload.PayloadFilesManager; -import org.glassfish.admin.payload.PayloadImpl; import org.glassfish.api.admin.CommandValidationException; import org.glassfish.api.admin.InvalidCommandException; import org.glassfish.api.admin.ParameterMap; @@ -152,7 +153,7 @@ public class RemoteAdminCommand { private boolean interactive = true; private boolean omitCache = true; - private List
requestHeaders = new ArrayList
(); + private final List
requestHeaders = new ArrayList<>(); /* * Set a default read timeout for URL connections. @@ -205,7 +206,7 @@ interface HttpCommand { * * @param urlConnection the connection to be configured */ - public void prepareConnection(HttpURLConnection urlConnection) throws IOException; + void prepareConnection(HttpURLConnection urlConnection) throws IOException; /** * Uses the configured and connected connection to read data, process it, etc. @@ -214,7 +215,7 @@ interface HttpCommand { * @throws CommandException * @throws IOException */ - public void useConnection(HttpURLConnection urlConnection) throws CommandException, IOException; + void useConnection(HttpURLConnection urlConnection) throws CommandException, IOException; } public RemoteAdminCommand(String name, String host, int port) throws CommandException { @@ -413,7 +414,7 @@ public String executeCommand(ParameterMap opts) throws CommandException { } String paramName = opt.getName(); - List paramValues = new ArrayList(options.get(paramName.toLowerCase(Locale.ENGLISH))); + List paramValues = new ArrayList<>(options.get(paramName.toLowerCase(Locale.ENGLISH))); if (!opt.getParam().alias().isEmpty() && !paramName.equalsIgnoreCase(opt.getParam().alias())) { paramValues.addAll(options.get(opt.getParam().alias().toLowerCase(Locale.ENGLISH))); } @@ -521,8 +522,9 @@ protected String reportAuthenticationException() { */ protected StringBuilder getCommandURI() { StringBuilder rv = new StringBuilder(ADMIN_URI_PATH); - if (scope != null) + if (scope != null) { rv.append(scope); + } rv.append(name).append(QUERY_STRING_INTRODUCER); return rv; } @@ -563,8 +565,9 @@ public void useConnection(final HttpURLConnection urlConnection) throws CommandE Payload.Inbound inboundPayload = PayloadImpl.Inbound.newInstance(responseContentType, in); - if (inboundPayload == null) + if (inboundPayload == null) { throw new IOException(strings.get("NoPayloadSupport", responseContentType)); + } PayloadFilesManager downloadedFilesMgr = new PayloadFilesManager.Perm(fileOutputDir, null, logger, new PayloadFilesManager.ActionReportHandler() { @Override @@ -681,8 +684,9 @@ private void doHttpCommand(String uriString, String httpMethod, HttpCommand cmd, } urlConnection.setRequestMethod(httpMethod); urlConnection.setReadTimeout(readTimeout); - if (connectTimeout >= 0) + if (connectTimeout >= 0) { urlConnection.setConnectTimeout(connectTimeout); + } addAdditionalHeaders(urlConnection); cmd.prepareConnection(urlConnection); @@ -1051,11 +1055,11 @@ private String chooseRequestMethod() { } } - private void handleResponse(ParameterMap params, InputStream in, int code, OutputStream userOut) throws IOException, CommandException { - if (userOut == null) { + private void handleResponse(ParameterMap params, InputStream in, int code, OutputStream out) throws IOException, CommandException { + if (out == null) { handleResponse(params, in, code); } else { - FileUtils.copy(in, userOut, 0); + FileUtils.copy(in, out); } } @@ -1068,9 +1072,7 @@ private void handleResponse(ParameterMap params, InputStream in, int code) throw } catch (RemoteSuccessException rse) { // save results output = rse.getMessage(); - assert rrm != null; - attrs = rrm.getMainAtts(); - return; + attrs = rrm == null ? Collections.emptyMap() : rrm.getMainAtts(); } catch (RemoteException rfe) { // XXX - gross if (rfe.getRemoteCause().indexOf("CommandNotFoundException") >= 0) { @@ -1110,14 +1112,15 @@ public void prepareConnection(HttpURLConnection urlConnection) { @Override public void useConnection(HttpURLConnection urlConnection) throws CommandException, IOException { - InputStream in = urlConnection.getInputStream(); - - String responseContentType = urlConnection.getContentType(); - logger.finer("Response Content-Type: " + responseContentType); - Payload.Inbound inboundPayload = PayloadImpl.Inbound.newInstance(responseContentType, in); - - if (inboundPayload == null) - throw new IOException(strings.get("NoPayloadSupport", responseContentType)); + Payload.Inbound inboundPayload; + try (InputStream in = urlConnection.getInputStream()) { + String responseContentType = urlConnection.getContentType(); + logger.finer("Response Content-Type: " + responseContentType); + inboundPayload = PayloadImpl.Inbound.newInstance(responseContentType, in); + if (inboundPayload == null) { + throw new IOException(strings.get("NoPayloadSupport", responseContentType)); + } + } boolean isReportProcessed = false; Iterator partIt = inboundPayload.parts(); @@ -1128,7 +1131,9 @@ public void useConnection(HttpURLConnection urlConnection) throws CommandExcepti */ if (!isReportProcessed) { metadataErrors = new StringBuilder(); - commandModel = parseMetadata(partIt.next().getInputStream(), metadataErrors); + try (InputStream inputStream = partIt.next().getInputStream()) { + commandModel = parseMetadata(inputStream, metadataErrors); + } logger.finer("fetchCommandModel: got command opts: " + commandModel); isReportProcessed = true; } else { @@ -1138,27 +1143,25 @@ public void useConnection(HttpURLConnection urlConnection) throws CommandExcepti } }); if (commandModel == null) { - if (metadataErrors != null) { - throw new InvalidCommandException(metadataErrors.toString()); - } else { + if (metadataErrors == null) { throw new InvalidCommandException(strings.get("unknownError")); } - } else { - this.commandModelFromCache = false; - if (logger.isLoggable(Level.FINEST)) { - logger.log(Level.FINEST, "Command model for {0} command fetched from remote server. [Duration: {1} nanos]", - new Object[] { name, System.nanoTime() - startNanos }); - } - //if (!omitCache) { - try { - AdminCacheUtils.getCache().put(createCommandCacheKey(), commandModel); - } catch (Exception ex) { - if (logger.isLoggable(Level.WARNING)) { - logger.log(Level.WARNING, AdminLoggerInfo.mCantPutToCache, new Object[] { createCommandCacheKey() }); - } + throw new InvalidCommandException(metadataErrors.toString()); + } + this.commandModelFromCache = false; + if (logger.isLoggable(Level.FINEST)) { + logger.log(Level.FINEST, "Command model for {0} command fetched from remote server. [Duration: {1} nanos]", + new Object[] { name, System.nanoTime() - startNanos }); + } + //if (!omitCache) { + try { + AdminCacheUtils.getCache().put(createCommandCacheKey(), commandModel); + } catch (Exception ex) { + if (logger.isLoggable(Level.WARNING)) { + logger.log(Level.WARNING, AdminLoggerInfo.mCantPutToCache, createCommandCacheKey()); } - //} } + //} } private String createCommandCacheKey() { @@ -1190,17 +1193,17 @@ protected String getCanonicalHost() { * @return the set of ValidOptions */ private CommandModel parseMetadata(InputStream in, StringBuilder errors) { - if (logger.isLoggable(Level.FINER)) { // XXX - assume "debug" == "FINER" - ByteArrayOutputStream baos = new ByteArrayOutputStream(); + if (logger.isLoggable(Level.FINER)) { try { - FileUtils.copy(in, baos, 0); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + FileUtils.copy(in, baos); + in = new ByteArrayInputStream(baos.toByteArray()); + String response = baos.toString(); + logger.finer("------- RAW METADATA RESPONSE ---------"); + logger.finer(response); + logger.finer("------- RAW METADATA RESPONSE ---------"); } catch (IOException ex) { } - in = new ByteArrayInputStream(baos.toByteArray()); - String response = baos.toString(); - logger.finer("------- RAW METADATA RESPONSE ---------"); - logger.finer(response); - logger.finer("------- RAW METADATA RESPONSE ---------"); } CachedCommandModel cm = new CachedCommandModel(name); @@ -1213,14 +1216,16 @@ private CommandModel parseMetadata(InputStream in, StringBuilder errors) { if (cmdnode == null) { Node report = doc.getElementsByTagName("action-report").item(0); String cause = getAttr(report.getAttributes(), "failure-cause"); - if (ok(cause)) + if (ok(cause)) { errors.append(cause); - else { + } else { Node mp = report.getFirstChild(); // message-part - if (mp != null) + if (mp != null) { cause = getAttr(mp.getAttributes(), "message"); - if (ok(cause)) + } + if (ok(cause)) { errors.append(cause); + } } // no command info, must be invalid command or something // wrong with command implementation @@ -1230,8 +1235,9 @@ private CommandModel parseMetadata(InputStream in, StringBuilder errors) { usage = getAttr(cmdattrs, "usage"); cm.setUsage(usage); String dashOk = getAttr(cmdattrs, "unknown-options-are-operands"); - if (dashOk != null) + if (dashOk != null) { cm.dashOk = Boolean.parseBoolean(dashOk); + } NodeList opts = doc.getElementsByTagName("option"); for (int i = 0; i < opts.getLength(); i++) { Node n = opts.item(i); @@ -1249,8 +1255,9 @@ private CommandModel parseMetadata(InputStream in, StringBuilder errors) { opt.promptAgain = getAttr(attributes, "promptAgain"); } cm.add(opt); - if (opt.getType() == File.class) + if (opt.getType() == File.class) { sawFile = true; + } } // should be only one operand item opts = doc.getElementsByTagName("operand"); @@ -1304,18 +1311,19 @@ private CommandModel parseMetadata(InputStream in, StringBuilder errors) { } private Class typeOf(String type) { - if (type.equals("STRING")) + if (type.equals("STRING")) { return String.class; - else if (type.equals("BOOLEAN")) + } else if (type.equals("BOOLEAN")) { return Boolean.class; - else if (type.equals("FILE")) + } else if (type.equals("FILE")) { return File.class; - else if (type.equals("PASSWORD")) + } else if (type.equals("PASSWORD")) { return String.class; - else if (type.equals("PROPERTIES")) + } else if (type.equals("PROPERTIES")) { return Properties.class; - else + } else { return String.class; + } } /** @@ -1323,10 +1331,11 @@ else if (type.equals("PROPERTIES")) */ private static String getAttr(NamedNodeMap attributes, String name) { Node n = attributes.getNamedItem(name); - if (n != null) + if (n != null) { return n.getNodeValue(); - else + } else { return null; + } } /** @@ -1343,8 +1352,9 @@ private void initializeDoUpload() throws CommandException { for (Map.Entry> param : options.entrySet()) { String paramName = param.getKey(); - if (paramName.equals("DEFAULT")) // operands handled below + if (paramName.equals("DEFAULT")) { // operands handled below continue; + } ParamModel opt = commandModel.getModelFor(paramName); if (opt != null && (opt.getType() == File.class || opt.getType() == File[].class)) { sawFile = true; @@ -1371,10 +1381,11 @@ private void initializeDoUpload() throws CommandException { logger.finer("Saw a file parameter"); // found a FILE param, is doUpload set? String upString = getOption("upload"); - if (ok(upString)) + if (ok(upString)) { doUpload = Boolean.parseBoolean(upString); - else + } else { doUpload = !isLocal(host) && sawUploadableFile; + } if (prohibitDirectoryUploads && sawDirectory && doUpload) { // oops, can't upload directories logger.finer("--upload=" + upString + ", doUpload=" + doUpload); @@ -1388,8 +1399,9 @@ private void initializeDoUpload() throws CommandException { // XXX - no remove method, have to copy it ParameterMap noptions = new ParameterMap(); for (Map.Entry> e : options.entrySet()) { - if (!e.getKey().equals("upload")) + if (!e.getKey().equals("upload")) { noptions.set(e.getKey(), e.getValue()); + } } options = noptions; } @@ -1401,8 +1413,9 @@ private void initializeDoUpload() throws CommandException { * Does the given hostname represent the local host? */ private static boolean isLocal(String hostname) { - if (hostname.equalsIgnoreCase("localhost")) // the common case + if (hostname.equalsIgnoreCase("localhost")) { // the common case return true; + } try { // let NetUtils do the hard work InetAddress ia = InetAddress.getByName(hostname); @@ -1422,8 +1435,9 @@ private static boolean isLocal(String hostname) { */ private ParamModel getOperandModel() { for (ParamModel pm : commandModel.getParameters()) { - if (pm.getParam().primary()) + if (pm.getParam().primary()) { return pm; + } } return null; } @@ -1434,16 +1448,18 @@ private ParamModel getOperandModel() { */ private String getOption(String name) { String val = options.getOne(name); - if (val == null) + if (val == null) { val = getFromEnvironment(name); + } if (val == null) { // no value, find the default ParamModel opt = commandModel.getModelFor(name); // if no value was specified and there's a default value, return it if (opt != null) { String def = opt.getParam().defaultValue(); - if (ok(def)) + if (ok(def)) { val = def; + } } } return val; diff --git a/nucleus/admin/util/src/main/java/com/sun/enterprise/admin/remote/RemoteResponseManager.java b/nucleus/admin/util/src/main/java/com/sun/enterprise/admin/remote/RemoteResponseManager.java index 427bce02721..b0b8c7f2f90 100644 --- a/nucleus/admin/util/src/main/java/com/sun/enterprise/admin/remote/RemoteResponseManager.java +++ b/nucleus/admin/util/src/main/java/com/sun/enterprise/admin/remote/RemoteResponseManager.java @@ -1,4 +1,5 @@ /* + * Copyright (c) 2022 Contributors to the Eclipse Foundation * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the @@ -16,13 +17,17 @@ package com.sun.enterprise.admin.remote; -import java.io.*; -import java.util.*; -import java.util.jar.*; -import java.util.logging.Logger; - -import com.sun.enterprise.util.io.FileUtils; import com.sun.enterprise.universal.i18n.LocalStringsImpl; +import com.sun.enterprise.util.io.FileUtils; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.Collections; +import java.util.Map; +import java.util.jar.Manifest; +import java.util.logging.Logger; import static com.sun.enterprise.util.StringUtils.ok; @@ -37,7 +42,16 @@ * @author bnevins */ public class RemoteResponseManager implements ResponseManager { + private static final LocalStringsImpl strings = new LocalStringsImpl(RemoteResponseManager.class); + private static final int HTTP_SUCCESS_CODE = 200; + + private final int code; + private final Logger logger; + private final InputStream responseStream; + private final String response; + private Manifest m; + private Map mainAtts = Collections.emptyMap(); public RemoteResponseManager(InputStream in, int code, Logger logger) throws RemoteException, IOException { this.code = code; @@ -46,19 +60,21 @@ public RemoteResponseManager(InputStream in, int code, Logger logger) throws Rem // make a copy of the stream. O/w if Manifest.read() blows up -- the // data would be gone! ByteArrayOutputStream baos = new ByteArrayOutputStream(); - FileUtils.copy(in, baos, 0); + FileUtils.copy(in, baos); responseStream = new ByteArrayInputStream(baos.toByteArray()); response = baos.toString(); - if (!ok(response)) + if (!ok(response)) { throw new RemoteFailureException(strings.get("emptyResponse")); + } logger.finer("------- RAW RESPONSE ---------"); logger.finer(response); logger.finer("------- RAW RESPONSE ---------"); } + @Override public void process() throws RemoteException { checkCode(); // Exception == Goodbye! try { @@ -94,12 +110,4 @@ private void handlePlainText() throws RemoteException { PlainTextManager mgr = new PlainTextManager(response); mgr.process(); } - - private int code; - private Logger logger; - final InputStream responseStream; - final String response; - private static final int HTTP_SUCCESS_CODE = 200; - private Manifest m; - private Map mainAtts = Collections.emptyMap(); } diff --git a/nucleus/admin/util/src/main/java/com/sun/enterprise/admin/remote/RemoteRestAdminCommand.java b/nucleus/admin/util/src/main/java/com/sun/enterprise/admin/remote/RemoteRestAdminCommand.java index 203ae80ef9b..12830039824 100644 --- a/nucleus/admin/util/src/main/java/com/sun/enterprise/admin/remote/RemoteRestAdminCommand.java +++ b/nucleus/admin/util/src/main/java/com/sun/enterprise/admin/remote/RemoteRestAdminCommand.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 Contributors to the Eclipse Foundation + * Copyright (c) 2022, 2023 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 @@ -42,6 +42,7 @@ import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; +import java.io.InputStream; import java.io.OutputStream; import java.io.PrintStream; import java.net.ConnectException; @@ -62,11 +63,13 @@ import java.util.Properties; import java.util.logging.Level; import java.util.logging.Logger; + import javax.net.ssl.SSLException; import org.codehaus.jettison.json.JSONArray; import org.codehaus.jettison.json.JSONException; import org.codehaus.jettison.json.JSONObject; +import org.glassfish.admin.payload.PayloadFilesManager; import org.glassfish.api.ActionReport; import org.glassfish.api.ActionReport.ExitCode; import org.glassfish.api.admin.AdminCommandState; @@ -78,7 +81,6 @@ import org.glassfish.api.admin.InvalidCommandException; import org.glassfish.api.admin.ParameterMap; import org.glassfish.api.admin.Payload; -import org.glassfish.admin.payload.PayloadFilesManager; import org.glassfish.common.util.admin.AuthTokenManager; /** @@ -158,7 +160,7 @@ public class RemoteRestAdminCommand extends AdminCommandEventBrokerImpl requestHeaders = new ArrayList
(); + private final List
requestHeaders = new ArrayList<>(); private boolean closeSse = false; private boolean enableCommandModelCache = true; @@ -217,7 +219,7 @@ interface HttpCommand { * * @param urlConnection the connection to be configured */ - public void prepareConnection(HttpURLConnection urlConnection) throws IOException; + void prepareConnection(HttpURLConnection urlConnection) throws IOException; /** * Uses the configured and connected connection to read data, process it, etc. @@ -226,7 +228,7 @@ interface HttpCommand { * @throws CommandException * @throws IOException */ - public void useConnection(HttpURLConnection urlConnection) throws CommandException, IOException; + void useConnection(HttpURLConnection urlConnection) throws CommandException, IOException; } public RemoteRestAdminCommand(String name, String host, int port) throws CommandException { @@ -565,7 +567,7 @@ private ParameterMap processParams(ParameterMap opts) throws CommandException { } String paramName = opt.getName(); - List paramValues = new ArrayList(options.get(paramName.toLowerCase(Locale.ENGLISH))); + List paramValues = new ArrayList<>(options.get(paramName.toLowerCase(Locale.ENGLISH))); if (!opt.getParam().alias().isEmpty() && !paramName.equalsIgnoreCase(opt.getParam().alias())) { paramValues.addAll(options.get(opt.getParam().alias().toLowerCase(Locale.ENGLISH))); } @@ -733,23 +735,19 @@ public void useConnection(final HttpURLConnection urlConnection) throws CommandE try { logger.log(Level.FINEST, "Response is SSE - about to read events"); closeSse = false; - ProprietaryReader reader = new GfSseEventReceiverProprietaryReader(); - GfSseEventReceiver eventReceiver = reader.readFrom(urlConnection.getInputStream(), resultMediaType); + final ProprietaryReader reader = new GfSseEventReceiverProprietaryReader(); + final GfSseEventReceiver eventReceiver = reader.readFrom(urlConnection.getInputStream(), resultMediaType); GfSseInboundEvent event; do { event = eventReceiver.readEvent(); if (event != null) { - if (logger.isLoggable(Level.FINEST)) { - logger.log(Level.FINEST, "Event: {0}", event.getName()); - } + logger.log(Level.FINEST, "Event: {0}", event.getName()); fireEvent(event.getName(), event); if (AdminCommandState.EVENT_STATE_CHANGED.equals(event.getName())) { AdminCommandState acs = event.getData(AdminCommandState.class, MEDIATYPE_JSON); if (acs.getId() != null) { instanceId = acs.getId(); - if (logger.isLoggable(Level.FINEST)) { - logger.log(Level.FINEST, "Command instance ID: {0}", instanceId); - } + logger.log(Level.FINEST, "Command instance ID: {0}", instanceId); } if (acs.getState() == AdminCommandState.State.COMPLETED || acs.getState() == AdminCommandState.State.RECORDED @@ -925,8 +923,9 @@ private static void addCombinedMessages(CliActionReport aReport, StringBuilder s && aReport.getFailureCause().getMessage().length() != 0) { failMsg = aReport.getFailureCause().getMessage(); if (!failMsg.equals(mainMsg)) { - if (sb.length() > 0) + if (sb.length() > 0) { sb.append(EOL); + } } sb.append(failMsg); } @@ -1262,9 +1261,10 @@ private String checkConnect(HttpURLConnection urlConnection) throws IOException, throw new CommandValidationException("Code: " + HttpURLConnection.HTTP_PRECON_FAILED + ": Cached CommandModel is invalid."); } if (code == HttpURLConnection.HTTP_NOT_FOUND) { - try { - throw new InvalidCommandException(ProprietaryReaderFactory.getReader(String.class, urlConnection.getContentType()) - .readFrom(urlConnection.getErrorStream(), urlConnection.getContentType())); + try (InputStream errorStream = urlConnection.getErrorStream()) { + throw new InvalidCommandException( + ProprietaryReaderFactory. getReader(String.class, urlConnection.getContentType()) + .readFrom(errorStream, urlConnection.getContentType())); } catch (IOException ioex) { throw new InvalidCommandException(urlConnection.getResponseMessage()); } @@ -1440,18 +1440,19 @@ protected String getCanonicalHost() { } private Class typeOf(String type) { - if (type.equals("STRING")) + if (type.equals("STRING")) { return String.class; - else if (type.equals("BOOLEAN")) + } else if (type.equals("BOOLEAN")) { return Boolean.class; - else if (type.equals("FILE")) + } else if (type.equals("FILE")) { return File.class; - else if (type.equals("PASSWORD")) + } else if (type.equals("PASSWORD")) { return String.class; - else if (type.equals("PROPERTIES")) + } else if (type.equals("PROPERTIES")) { return Properties.class; - else + } else { return String.class; + } } /** @@ -1468,8 +1469,9 @@ private void initializeDoUpload() throws CommandException { for (Map.Entry> param : options.entrySet()) { String paramName = param.getKey(); - if (paramName.equals("DEFAULT")) // operands handled below + if (paramName.equals("DEFAULT")) { // operands handled below continue; + } ParamModel opt = commandModel.getModelFor(paramName); if (opt != null && (opt.getType() == File.class || opt.getType() == File[].class)) { sawFile = true; @@ -1514,8 +1516,9 @@ private void initializeDoUpload() throws CommandException { // XXX - no remove method, have to copy it ParameterMap noptions = new ParameterMap(); for (Map.Entry> e : options.entrySet()) { - if (!e.getKey().equals("upload")) + if (!e.getKey().equals("upload")) { noptions.set(e.getKey(), e.getValue()); + } } options = noptions; } @@ -1527,8 +1530,9 @@ private void initializeDoUpload() throws CommandException { * Does the given hostname represent the local host? */ private static boolean isLocal(String hostname) { - if (hostname.equalsIgnoreCase("localhost")) // the common case + if (hostname.equalsIgnoreCase("localhost")) { // the common case return true; + } try { // let NetUtils do the hard work InetAddress ia = InetAddress.getByName(hostname); @@ -1548,8 +1552,9 @@ private static boolean isLocal(String hostname) { */ private ParamModel getOperandModel() { for (ParamModel pm : commandModel.getParameters()) { - if (pm.getParam().primary()) + if (pm.getParam().primary()) { return pm; + } } return null; } diff --git a/nucleus/admin/util/src/main/java/com/sun/enterprise/admin/remote/reader/ActionReportJsonProprietaryReader.java b/nucleus/admin/util/src/main/java/com/sun/enterprise/admin/remote/reader/ActionReportJsonProprietaryReader.java index d10a9760f4c..7658e4d4f56 100644 --- a/nucleus/admin/util/src/main/java/com/sun/enterprise/admin/remote/reader/ActionReportJsonProprietaryReader.java +++ b/nucleus/admin/util/src/main/java/com/sun/enterprise/admin/remote/reader/ActionReportJsonProprietaryReader.java @@ -1,4 +1,5 @@ /* + * Copyright (c) 2022 Contributors to the Eclipse Foundation * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the @@ -18,8 +19,12 @@ import com.sun.enterprise.admin.util.AdminLoggerInfo; import com.sun.enterprise.util.io.FileUtils; -import java.io.*; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; import java.net.HttpURLConnection; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; @@ -28,6 +33,7 @@ import java.util.Properties; import java.util.logging.Level; import java.util.logging.Logger; + import org.codehaus.jettison.json.JSONArray; import org.codehaus.jettison.json.JSONException; import org.codehaus.jettison.json.JSONObject; @@ -39,7 +45,7 @@ * * @author mmares */ -public class ActionReportJsonProprietaryReader implements ProprietaryReader { +public final class ActionReportJsonProprietaryReader implements ProprietaryReader { static class LoggerRef { private static final Logger logger = AdminLoggerInfo.getLogger(); @@ -57,11 +63,14 @@ public ActionReport readFrom(final HttpURLConnection urlConnection) throws IOExc @Override public ActionReport readFrom(final InputStream is, final String contentType) throws IOException { ByteArrayOutputStream baos = new ByteArrayOutputStream(); - FileUtils.copy(is, baos, 0); - String str = baos.toString("UTF-8"); + try { + FileUtils.copy(is, baos); + } finally { + is.close(); + } + String str = baos.toString(StandardCharsets.UTF_8); try { JSONObject json = new JSONObject(str); - //JSONObject jsonObject = json.getJSONObject("action-report"); CliActionReport result = new CliActionReport(); fillActionReport(result, json); return result; diff --git a/nucleus/admin/util/src/main/java/com/sun/enterprise/admin/remote/reader/AdminCommandStateJsonProprietaryReader.java b/nucleus/admin/util/src/main/java/com/sun/enterprise/admin/remote/reader/AdminCommandStateJsonProprietaryReader.java index b61b1a37b8b..4706bb76b12 100644 --- a/nucleus/admin/util/src/main/java/com/sun/enterprise/admin/remote/reader/AdminCommandStateJsonProprietaryReader.java +++ b/nucleus/admin/util/src/main/java/com/sun/enterprise/admin/remote/reader/AdminCommandStateJsonProprietaryReader.java @@ -1,4 +1,5 @@ /* + * Copyright (c) 2022 Contributors to the Eclipse Foundation * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the @@ -19,12 +20,15 @@ import com.sun.enterprise.admin.remote.AdminCommandStateImpl; import com.sun.enterprise.admin.util.AdminLoggerInfo; import com.sun.enterprise.util.io.FileUtils; + import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.net.HttpURLConnection; +import java.nio.charset.StandardCharsets; import java.util.logging.Level; import java.util.logging.Logger; + import org.codehaus.jettison.json.JSONException; import org.codehaus.jettison.json.JSONObject; import org.glassfish.api.admin.AdminCommandState; @@ -33,7 +37,7 @@ * * @author mmares */ -public class AdminCommandStateJsonProprietaryReader implements ProprietaryReader { +public final class AdminCommandStateJsonProprietaryReader implements ProprietaryReader { static class LoggerRef { private static final Logger logger = AdminLoggerInfo.getLogger(); @@ -51,8 +55,12 @@ public AdminCommandState readFrom(HttpURLConnection urlConnection) throws IOExce @Override public AdminCommandState readFrom(final InputStream is, final String contentType) throws IOException { ByteArrayOutputStream baos = new ByteArrayOutputStream(); - FileUtils.copy(is, baos, 0); - String str = baos.toString("UTF-8"); + try { + FileUtils.copy(is, baos); + } finally { + is.close(); + } + String str = baos.toString(StandardCharsets.UTF_8); try { JSONObject json = new JSONObject(str); return readAdminCommandState(json); diff --git a/nucleus/admin/util/src/main/java/com/sun/enterprise/admin/remote/reader/MultipartProprietaryReader.java b/nucleus/admin/util/src/main/java/com/sun/enterprise/admin/remote/reader/MultipartProprietaryReader.java index acf91ec8eaa..508064b901f 100644 --- a/nucleus/admin/util/src/main/java/com/sun/enterprise/admin/remote/reader/MultipartProprietaryReader.java +++ b/nucleus/admin/util/src/main/java/com/sun/enterprise/admin/remote/reader/MultipartProprietaryReader.java @@ -1,4 +1,5 @@ /* + * Copyright (c) 2022 Contributors to the Eclipse Foundation * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the @@ -19,12 +20,14 @@ import com.sun.enterprise.admin.remote.ParamsWithPayload; import com.sun.enterprise.admin.remote.RestPayloadImpl; import com.sun.enterprise.util.StringUtils; + import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.net.HttpURLConnection; import java.util.List; import java.util.Properties; + import org.glassfish.api.ActionReport; import org.glassfish.api.admin.ParameterMap; import org.jvnet.mimepull.MIMEConfig; @@ -35,7 +38,7 @@ * * @author martinmares */ -public class MultipartProprietaryReader implements ProprietaryReader { +public final class MultipartProprietaryReader implements ProprietaryReader { private final ActionReportJsonProprietaryReader actionReportReader; @@ -69,50 +72,54 @@ public ParamsWithPayload readFrom(final InputStream is, final String contentType if (!StringUtils.ok(boundary)) { throw new IOException("ContentType does not define boundary"); } - final MIMEMessage mimeMessage = new MIMEMessage(is, boundary, new MIMEConfig()); - //Parse - for (MIMEPart mimePart : mimeMessage.getAttachments()) { - String cd = getFirst(mimePart.getHeader("Content-Disposition")); - if (!StringUtils.ok(cd)) { - cd = "file"; - } - cd = cd.trim(); - Properties cdParams = parseHeaderParams(cd); - //3 types of content disposition - if (cd.startsWith("form-data")) { - //COMMAND PARAMETER - if (!StringUtils.ok(cdParams.getProperty("name"))) { - throw new IOException("Form-data Content-Disposition does not contains name parameter."); - } - if (parameters == null) { - parameters = new ParameterMap(); - } - parameters.add(cdParams.getProperty("name"), stream2String(mimePart.readOnce())); - } else if (mimePart.getContentType() != null && mimePart.getContentType().startsWith("application/json")) { - //ACTION REPORT - actionReport = actionReportReader.readFrom(mimePart.readOnce(), "application/json"); - } else { - //PAYLOAD - String name = "noname"; - if (cdParams.containsKey("name")) { - name = cdParams.getProperty("name"); - name = new String(name.getBytes("ISO8859-1"), "UTF-8"); - } else if (cdParams.containsKey("filename")) { - name = cdParams.getProperty("filename"); - } - if (payload == null) { - payload = new RestPayloadImpl.Inbound(); + try (MIMEMessage mimeMessage = new MIMEMessage(is, boundary, new MIMEConfig())) { + // Parse + for (MIMEPart mimePart : mimeMessage.getAttachments()) { + String cd = getFirst(mimePart.getHeader("Content-Disposition")); + if (!StringUtils.ok(cd)) { + cd = "file"; } - String ct = mimePart.getContentType(); - if (!StringUtils.ok(ct) || ct.trim().startsWith("text/plain")) { - payload.add(name, stream2String(mimePart.readOnce()), mimePart.getAllHeaders()); + cd = cd.trim(); + Properties cdParams = parseHeaderParams(cd); + // 3 types of content disposition + if (cd.startsWith("form-data")) { + // COMMAND PARAMETER + if (!StringUtils.ok(cdParams.getProperty("name"))) { + throw new IOException("Form-data Content-Disposition does not contains name parameter."); + } + if (parameters == null) { + parameters = new ParameterMap(); + } + parameters.add(cdParams.getProperty("name"), stream2String(mimePart.readOnce())); + } else if (mimePart.getContentType() != null + && mimePart.getContentType().startsWith("application/json")) { + // ACTION REPORT + actionReport = actionReportReader.readFrom(mimePart.readOnce(), "application/json"); } else { - payload.add(name, mimePart.read(), ct, mimePart.getAllHeaders()); + // PAYLOAD + String name = "noname"; + if (cdParams.containsKey("name")) { + name = cdParams.getProperty("name"); + name = new String(name.getBytes("ISO8859-1"), "UTF-8"); + } else if (cdParams.containsKey("filename")) { + name = cdParams.getProperty("filename"); + } + if (payload == null) { + payload = new RestPayloadImpl.Inbound(); + } + String ct = mimePart.getContentType(); + if (!StringUtils.ok(ct) || ct.trim().startsWith("text/plain")) { + payload.add(name, stream2String(mimePart.readOnce()), mimePart.getAllHeaders()); + } else { + payload.add(name, mimePart.read(), ct, mimePart.getAllHeaders()); + } } } + // Result + return new ParamsWithPayload(payload, parameters, actionReport); + } finally { + is.close(); } - //Result - return new ParamsWithPayload(payload, parameters, actionReport); } /** diff --git a/nucleus/admin/util/src/main/java/com/sun/enterprise/admin/remote/reader/ParamsWithPayloadJsonProprietaryReader.java b/nucleus/admin/util/src/main/java/com/sun/enterprise/admin/remote/reader/ParamsWithPayloadJsonProprietaryReader.java index 2452d1ecd97..1e114b46e98 100644 --- a/nucleus/admin/util/src/main/java/com/sun/enterprise/admin/remote/reader/ParamsWithPayloadJsonProprietaryReader.java +++ b/nucleus/admin/util/src/main/java/com/sun/enterprise/admin/remote/reader/ParamsWithPayloadJsonProprietaryReader.java @@ -1,4 +1,5 @@ /* + * Copyright (c) 2022 Contributors to the Eclipse Foundation * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the @@ -22,10 +23,9 @@ import java.net.HttpURLConnection; /** - * * @author martinmares */ -public class ParamsWithPayloadJsonProprietaryReader implements ProprietaryReader { +public final class ParamsWithPayloadJsonProprietaryReader implements ProprietaryReader { private final ActionReportJsonProprietaryReader delegate; diff --git a/nucleus/admin/util/src/main/java/com/sun/enterprise/admin/remote/reader/ProgressStatusDTOJsonProprietaryReader.java b/nucleus/admin/util/src/main/java/com/sun/enterprise/admin/remote/reader/ProgressStatusDTOJsonProprietaryReader.java index c0dfbfc99f8..eee6c6f4ac4 100644 --- a/nucleus/admin/util/src/main/java/com/sun/enterprise/admin/remote/reader/ProgressStatusDTOJsonProprietaryReader.java +++ b/nucleus/admin/util/src/main/java/com/sun/enterprise/admin/remote/reader/ProgressStatusDTOJsonProprietaryReader.java @@ -1,4 +1,5 @@ /* + * Copyright (c) 2022 Contributors to the Eclipse Foundation * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the @@ -16,12 +17,14 @@ package com.sun.enterprise.admin.remote.reader; -import java.io.IOException; -import java.io.InputStream; -import java.net.HttpURLConnection; import com.fasterxml.jackson.core.JsonFactory; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonToken; + +import java.io.IOException; +import java.io.InputStream; +import java.net.HttpURLConnection; + import org.glassfish.api.admin.progress.ProgressStatusDTO; import org.glassfish.api.admin.progress.ProgressStatusDTO.ChildProgressStatusDTO; @@ -29,7 +32,7 @@ * * @author mmares */ -public class ProgressStatusDTOJsonProprietaryReader implements ProprietaryReader { +public final class ProgressStatusDTOJsonProprietaryReader implements ProprietaryReader { private static final JsonFactory factory = new JsonFactory(); @@ -44,7 +47,7 @@ public ProgressStatusDTO readFrom(final HttpURLConnection urlConnection) throws @Override public ProgressStatusDTO readFrom(final InputStream is, final String contentType) throws IOException { - JsonParser jp = factory.createJsonParser(is); + JsonParser jp = factory.createParser(is); try { JsonToken token = jp.nextToken(); //sorounding object jp.nextToken(); //Name progress-status @@ -55,6 +58,7 @@ public ProgressStatusDTO readFrom(final InputStream is, final String contentType return readProgressStatus(jp); } finally { jp.close(); + is.close(); } } diff --git a/nucleus/admin/util/src/main/java/com/sun/enterprise/admin/remote/reader/ProgressStatusEventJsonProprietaryReader.java b/nucleus/admin/util/src/main/java/com/sun/enterprise/admin/remote/reader/ProgressStatusEventJsonProprietaryReader.java index 7ea97670e77..0ee0879bda1 100644 --- a/nucleus/admin/util/src/main/java/com/sun/enterprise/admin/remote/reader/ProgressStatusEventJsonProprietaryReader.java +++ b/nucleus/admin/util/src/main/java/com/sun/enterprise/admin/remote/reader/ProgressStatusEventJsonProprietaryReader.java @@ -1,4 +1,5 @@ /* + * Copyright (c) 2022 Contributors to the Eclipse Foundation * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the @@ -16,12 +17,14 @@ package com.sun.enterprise.admin.remote.reader; -import java.io.IOException; -import java.io.InputStream; -import java.net.HttpURLConnection; import com.fasterxml.jackson.core.JsonFactory; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonToken; + +import java.io.IOException; +import java.io.InputStream; +import java.net.HttpURLConnection; + import org.glassfish.api.admin.progress.ProgressStatusEvent; import org.glassfish.api.admin.progress.ProgressStatusEventComplete; import org.glassfish.api.admin.progress.ProgressStatusEventCreateChild; @@ -29,10 +32,9 @@ import org.glassfish.api.admin.progress.ProgressStatusEventSet; /** - * * @author mmares */ -public class ProgressStatusEventJsonProprietaryReader implements ProprietaryReader { +public final class ProgressStatusEventJsonProprietaryReader implements ProprietaryReader { private static final JsonFactory factory = new JsonFactory(); @@ -47,7 +49,7 @@ public ProgressStatusEvent readFrom(HttpURLConnection urlConnection) throws IOEx @Override public ProgressStatusEvent readFrom(final InputStream is, final String contentType) throws IOException { - JsonParser jp = factory.createJsonParser(is); + JsonParser jp = factory.createParser(is); try { JsonToken token = jp.nextToken(); //sorounding object jp.nextToken(); //Name progress-status-event @@ -59,6 +61,7 @@ public ProgressStatusEvent readFrom(final InputStream is, final String contentTy return readProgressStatusEvent(jp); } finally { jp.close(); + is.close(); } } diff --git a/nucleus/admin/util/src/main/java/com/sun/enterprise/admin/remote/reader/ProprietaryReader.java b/nucleus/admin/util/src/main/java/com/sun/enterprise/admin/remote/reader/ProprietaryReader.java index ff4a754e46d..416b2bc430b 100644 --- a/nucleus/admin/util/src/main/java/com/sun/enterprise/admin/remote/reader/ProprietaryReader.java +++ b/nucleus/admin/util/src/main/java/com/sun/enterprise/admin/remote/reader/ProprietaryReader.java @@ -1,4 +1,5 @@ /* + * Copyright (c) 2022 Contributors to the Eclipse Foundation * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the @@ -18,18 +19,22 @@ import java.io.IOException; import java.io.InputStream; -import java.net.HttpURLConnection; /** - * * @author martinmares */ public interface ProprietaryReader { - public boolean isReadable(final Class type, final String contentType); - - // public T readFrom(final HttpURLConnection urlConnection) throws IOException; + boolean isReadable(final Class type, final String contentType); - public T readFrom(final InputStream is, final String contentType) throws IOException; + /** + * Reads and closes the stream, or can transfer both respnsibilities to a returned object. + * + * @param stream + * @param contentType + * @return T + * @throws IOException + */ + T readFrom(final InputStream stream, final String contentType) throws IOException; } diff --git a/nucleus/admin/util/src/main/java/com/sun/enterprise/admin/remote/reader/StringProprietaryReader.java b/nucleus/admin/util/src/main/java/com/sun/enterprise/admin/remote/reader/StringProprietaryReader.java index ede47b7a4be..59470039e7a 100644 --- a/nucleus/admin/util/src/main/java/com/sun/enterprise/admin/remote/reader/StringProprietaryReader.java +++ b/nucleus/admin/util/src/main/java/com/sun/enterprise/admin/remote/reader/StringProprietaryReader.java @@ -1,4 +1,5 @@ /* + * Copyright (c) 2022 Contributors to the Eclipse Foundation * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the @@ -20,12 +21,12 @@ import java.io.IOException; import java.io.InputStream; import java.net.HttpURLConnection; +import java.nio.charset.StandardCharsets; /** - * * @author martinmares */ -public class StringProprietaryReader implements ProprietaryReader { +public final class StringProprietaryReader implements ProprietaryReader { @Override public boolean isReadable(Class type, String mimetype) { @@ -39,12 +40,16 @@ public String readFrom(final HttpURLConnection urlConnection) throws IOException @Override public String readFrom(final InputStream is, final String contentType) throws IOException { ByteArrayOutputStream baos = new ByteArrayOutputStream(); - byte[] buff = new byte[512]; - int count; - while ((count = is.read(buff)) > 0) { - baos.write(buff, 0, count); + try { + byte[] buff = new byte[512]; + int count; + while ((count = is.read(buff)) > 0) { + baos.write(buff, 0, count); + } + } finally { + is.close(); } - return baos.toString("UTF-8"); + return baos.toString(StandardCharsets.UTF_8); } } diff --git a/nucleus/admin/util/src/main/java/com/sun/enterprise/admin/util/cache/ByteArrayDataProvider.java b/nucleus/admin/util/src/main/java/com/sun/enterprise/admin/util/cache/ByteArrayDataProvider.java index 6b06ae72f4d..401b5cc15da 100644 --- a/nucleus/admin/util/src/main/java/com/sun/enterprise/admin/util/cache/ByteArrayDataProvider.java +++ b/nucleus/admin/util/src/main/java/com/sun/enterprise/admin/util/cache/ByteArrayDataProvider.java @@ -1,4 +1,5 @@ /* + * Copyright (c) 2022 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 @@ -17,10 +18,12 @@ package com.sun.enterprise.admin.util.cache; import com.sun.enterprise.util.io.FileUtils; + import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; + import org.jvnet.hk2.annotations.Service; /** @@ -44,7 +47,7 @@ public void writeToStream(Object o, OutputStream stream) throws IOException { @Override public Object toInstance(InputStream stream, Class clazz) throws IOException { ByteArrayOutputStream baos = new ByteArrayOutputStream(); - FileUtils.copy(stream, baos, 0); + FileUtils.copy(stream, baos); return baos.toByteArray(); } diff --git a/nucleus/admin/util/src/main/java/com/sun/enterprise/admin/util/cache/StringDataProvider.java b/nucleus/admin/util/src/main/java/com/sun/enterprise/admin/util/cache/StringDataProvider.java index a4be6f64fe1..11b8834c109 100644 --- a/nucleus/admin/util/src/main/java/com/sun/enterprise/admin/util/cache/StringDataProvider.java +++ b/nucleus/admin/util/src/main/java/com/sun/enterprise/admin/util/cache/StringDataProvider.java @@ -49,7 +49,7 @@ public void writeToStream(Object o, OutputStream stream) throws IOException { @Override public Object toInstance(InputStream stream, Class clazz) throws IOException { ByteArrayOutputStream baos = new ByteArrayOutputStream(); - FileUtils.copy(stream, baos, 0); + FileUtils.copy(stream, baos); return new String(baos.toByteArray(), StandardCharsets.UTF_8); } diff --git a/nucleus/cluster/admin/src/main/java/com/sun/enterprise/v3/admin/cluster/CreateNodeSshCommand.java b/nucleus/cluster/admin/src/main/java/com/sun/enterprise/v3/admin/cluster/CreateNodeSshCommand.java index 4fa73529ecc..4edf4c56ef5 100644 --- a/nucleus/cluster/admin/src/main/java/com/sun/enterprise/v3/admin/cluster/CreateNodeSshCommand.java +++ b/nucleus/cluster/admin/src/main/java/com/sun/enterprise/v3/admin/cluster/CreateNodeSshCommand.java @@ -1,4 +1,5 @@ /* + * Copyright (c) 2022 Contributors to the Eclipse Foundation * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the @@ -17,21 +18,25 @@ package com.sun.enterprise.v3.admin.cluster; import com.sun.enterprise.config.serverbeans.Nodes; -import java.util.List; -import java.util.ArrayList; -import com.sun.enterprise.util.cluster.RemoteType; import com.sun.enterprise.util.StringUtils; -import org.glassfish.api.I18n; -import org.glassfish.api.Param; -import org.glassfish.api.admin.*; -import jakarta.inject.Inject; - +import com.sun.enterprise.util.cluster.RemoteType; -import org.jvnet.hk2.annotations.Service; -import org.jvnet.hk2.component.*; +import java.io.File; +import java.util.ArrayList; +import java.util.List; +import org.glassfish.api.I18n; +import org.glassfish.api.Param; +import org.glassfish.api.admin.AdminCommandContext; +import org.glassfish.api.admin.CommandValidationException; +import org.glassfish.api.admin.ExecuteOn; +import org.glassfish.api.admin.ParameterMap; +import org.glassfish.api.admin.RestEndpoint; +import org.glassfish.api.admin.RestEndpoints; +import org.glassfish.api.admin.RuntimeType; import org.glassfish.cluster.ssh.util.SSHUtil; import org.glassfish.hk2.api.PerLookup; +import org.jvnet.hk2.annotations.Service; /** * Remote AdminCommand to create and ssh node. This command is run only on DAS. @@ -116,7 +121,10 @@ protected final void populateParameters(ParameterMap pmap) { @Override protected final void populateCommandArgs(List args) { if (sshkeyfile == null) { - sshkeyfile = SSHUtil.getExistingKeyFile(); + File file = SSHUtil.getExistingKeyFile(); + if (file != null) { + sshkeyfile = file.getAbsolutePath(); + } } if (sshkeyfile != null) { @@ -136,7 +144,7 @@ protected final void populateCommandArgs(List args) { */ @Override protected List getPasswords() { - List list = new ArrayList(); + List list = new ArrayList<>(); NodeUtils nUtils = new NodeUtils(habitat, logger); list.add("AS_ADMIN_SSHPASSWORD=" + nUtils.sshL.expandPasswordAlias(remotePassword)); diff --git a/nucleus/cluster/admin/src/main/java/com/sun/enterprise/v3/admin/cluster/NodeUtils.java b/nucleus/cluster/admin/src/main/java/com/sun/enterprise/v3/admin/cluster/NodeUtils.java index c1d891560d8..cbaf592102f 100644 --- a/nucleus/cluster/admin/src/main/java/com/sun/enterprise/v3/admin/cluster/NodeUtils.java +++ b/nucleus/cluster/admin/src/main/java/com/sun/enterprise/v3/admin/cluster/NodeUtils.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 Contributors to the Eclipse Foundation + * Copyright (c) 2022, 2023 Contributors to the Eclipse Foundation * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the @@ -57,8 +57,7 @@ public class NodeUtils { public static final String NODE_DEFAULT_SSH_PORT = "22"; public static final String NODE_DEFAULT_REMOTE_USER = "${user.name}"; - static final String NODE_DEFAULT_INSTALLDIR = - "${com.sun.aas.productRoot}"; + static final String NODE_DEFAULT_INSTALLDIR = "${com.sun.aas.productRoot}"; // Command line option parameter names static final String PARAM_NODEHOST = "nodehost"; static final String PARAM_INSTALLDIR = "installdir"; @@ -350,11 +349,12 @@ private void validateSSHConnection(ParameterMap map) throws // Those aliases are handled by sshLauncher String resolvedInstallDir = resolver.resolve(installdir); + String keyFile = resolver.resolve(sshkeyfile); sshL.validate(resolver.resolve(nodehost), port, resolver.resolve(sshuser), sshpassword, - resolver.resolve(sshkeyfile), + keyFile == null ? null : new File(keyFile), sshkeypassphrase, resolvedInstallDir, // Landmark file to ensure valid GF install diff --git a/nucleus/cluster/admin/src/main/java/com/sun/enterprise/v3/admin/cluster/SecureAdminBootstrapHelper.java b/nucleus/cluster/admin/src/main/java/com/sun/enterprise/v3/admin/cluster/SecureAdminBootstrapHelper.java index 6c4b33b6dd8..e4a123ffc69 100644 --- a/nucleus/cluster/admin/src/main/java/com/sun/enterprise/v3/admin/cluster/SecureAdminBootstrapHelper.java +++ b/nucleus/cluster/admin/src/main/java/com/sun/enterprise/v3/admin/cluster/SecureAdminBootstrapHelper.java @@ -1,4 +1,5 @@ /* + * Copyright (c) 2022 Contributors to the Eclipse Foundation * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the @@ -18,20 +19,20 @@ import com.jcraft.jsch.JSchException; import com.jcraft.jsch.SftpException; -import com.sun.enterprise.util.cluster.RemoteType; import com.sun.enterprise.config.serverbeans.Node; -import com.sun.enterprise.util.io.FileUtils; +import com.sun.enterprise.util.cluster.RemoteType; + import java.io.BufferedInputStream; -import java.io.BufferedOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; -import java.io.OutputStream; import java.net.URI; +import java.nio.file.Files; import java.util.logging.Level; import java.util.logging.Logger; + import org.glassfish.cluster.ssh.launcher.SSHLauncher; import org.glassfish.cluster.ssh.sftp.SFTPClient; import org.glassfish.hk2.api.ServiceLocator; @@ -397,7 +398,7 @@ public void copyBootstrapFiles() throws IOException { for (String relativePathToFile : SECURE_ADMIN_FILE_REL_URIS_TO_COPY) { final File origin = new File(existingInstanceDirURI.resolve(relativePathToFile)); final File dest = new File(newInstanceDirURI.resolve(relativePathToFile)); - FileUtils.copyFile(origin, dest); + Files.copy(origin.toPath(), dest.toPath()); } } diff --git a/nucleus/cluster/admin/src/main/java/com/sun/enterprise/v3/admin/cluster/SetupSshCommand.java b/nucleus/cluster/admin/src/main/java/com/sun/enterprise/v3/admin/cluster/SetupSshCommand.java index 913674e1671..5f240629cc7 100644 --- a/nucleus/cluster/admin/src/main/java/com/sun/enterprise/v3/admin/cluster/SetupSshCommand.java +++ b/nucleus/cluster/admin/src/main/java/com/sun/enterprise/v3/admin/cluster/SetupSshCommand.java @@ -1,4 +1,5 @@ /* + * Copyright (c) 2022 Contributors to the Eclipse Foundation * Copyright (c) 2011, 2018 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the @@ -18,21 +19,28 @@ import com.sun.enterprise.universal.glassfish.TokenResolver; import com.sun.enterprise.util.StringUtils; + +import jakarta.inject.Inject; + import java.io.File; import java.io.IOException; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; + import org.glassfish.api.ActionReport; import org.glassfish.api.I18n; import org.glassfish.api.Param; -import org.glassfish.api.admin.*; +import org.glassfish.api.admin.AdminCommand; +import org.glassfish.api.admin.AdminCommandContext; +import org.glassfish.api.admin.CommandException; +import org.glassfish.api.admin.CommandLock; +import org.glassfish.api.admin.ExecuteOn; +import org.glassfish.api.admin.RuntimeType; import org.glassfish.cluster.ssh.launcher.SSHLauncher; import org.glassfish.cluster.ssh.util.SSHUtil; -import jakarta.inject.Inject; - -import org.jvnet.hk2.annotations.Service; import org.glassfish.hk2.api.PerLookup; +import org.jvnet.hk2.annotations.Service; /** * This is a remote command implementation of setup-ssh local command @@ -72,48 +80,47 @@ private void validate() throws CommandException { if (!StringUtils.ok(sshpassword)) { throw new CommandException(Strings.get("setup.ssh.null.sshpass")); - } else { - // obtain real password - realPass = sshL.expandPasswordAlias(sshpassword); + } + // obtain real password + realPass = sshL.expandPasswordAlias(sshpassword); - if (realPass == null) { - throw new CommandException(Strings.get("setup.ssh.unalias.error", sshpassword)); - } + if (realPass == null) { + throw new CommandException(Strings.get("setup.ssh.unalias.error", sshpassword)); } if (sshkeyfile == null) { //if user hasn't specified a key file and there is no key file at default //location, then generate one - String existingKey = SSHUtil.getExistingKeyFile(); + File existingKey = SSHUtil.getExistingKeyFile(); if (existingKey == null) { - sshkeyfile = SSHUtil.getDefaultKeyFile(); + sshkeyfile = SSHUtil.getDefaultKeyFile().getAbsolutePath(); if (!generatekey) { throw new CommandException(Strings.get("setup.ssh.no.keyfile")); } - } - else { - sshkeyfile = existingKey; - if (SSHUtil.isEncryptedKey(sshkeyfile)) { + } else { + sshkeyfile = existingKey.getAbsolutePath(); + if (SSHUtil.isEncryptedKey(existingKey)) { sshkeypassphrase = getSSHPassphrase(); } } - } - else { - if (!isAbsolutePath(sshkeyfile)) { - throw new CommandException(Strings.get("setup.ssh.invalid.path", sshkeyfile)); + } else { + File keyFile = new File(sshkeyfile); + if (!keyFile.isAbsolute()) { + throw new CommandException(Strings.get("setup.ssh.invalid.path", keyFile)); } - SSHUtil.validateKeyFile(sshkeyfile); - if (SSHUtil.isEncryptedKey(sshkeyfile)) { + SSHUtil.validateKeyFile(keyFile); + if (SSHUtil.isEncryptedKey(keyFile)) { sshkeypassphrase = getSSHPassphrase(); } } if (sshpublickeyfile != null) { - if (!isAbsolutePath(sshpublickeyfile)) { - throw new CommandException(Strings.get("setup.ssh.invalid.path", sshpublickeyfile)); + File keyFile = new File(sshpublickeyfile); + if (!keyFile.isAbsolute()) { + throw new CommandException(Strings.get("setup.ssh.invalid.path", keyFile)); } - SSHUtil.validateKeyFile(sshpublickeyfile); + SSHUtil.validateKeyFile(keyFile); } } @@ -135,8 +142,9 @@ public final void execute(AdminCommandContext context) { } for (String node : hosts) { - sshL.init(user, node, port, realPass, sshkeyfile, sshkeypassphrase, logger); - if (generatekey ) { + File keyFile = sshkeyfile == null ? null : new File(sshkeyfile); + sshL.init(user, node, port, realPass, keyFile, sshkeypassphrase, logger); + if (generatekey) { if (sshkeyfile != null || SSHUtil.getExistingKeyFile() != null) { if (sshL.checkConnection()) { logger.info(Strings.get("setup.ssh.already.configured", user, node)); @@ -168,13 +176,6 @@ public final void execute(AdminCommandContext context) { } } - private boolean isAbsolutePath(String path) { - boolean ret = false; - File f = new File(path); - if (f.isAbsolute()) - ret = true; - return ret; - } /** * Get SSH key passphrase. Obtain real passphrase in case it is an alias. diff --git a/nucleus/cluster/cli/src/main/java/com/sun/enterprise/admin/cli/cluster/InstallNodeSshCommand.java b/nucleus/cluster/cli/src/main/java/com/sun/enterprise/admin/cli/cluster/InstallNodeSshCommand.java index 8b790097dd3..f88b2cb6553 100644 --- a/nucleus/cluster/cli/src/main/java/com/sun/enterprise/admin/cli/cluster/InstallNodeSshCommand.java +++ b/nucleus/cluster/cli/src/main/java/com/sun/enterprise/admin/cli/cluster/InstallNodeSshCommand.java @@ -80,20 +80,18 @@ protected void validate() throws CommandException { if (sshkeyfile == null) { //if user hasn't specified a key file check if key exists in //default location - String existingKey = SSHUtil.getExistingKeyFile(); + File existingKey = SSHUtil.getExistingKeyFile(); if (existingKey == null) { promptPass = true; + } else { + sshkeyfile = existingKey.getAbsolutePath(); } - else { - sshkeyfile = existingKey; - } - } - else { + } else { validateKey(sshkeyfile); } //we need the key passphrase if key is encrypted - if (sshkeyfile != null && SSHUtil.isEncryptedKey(sshkeyfile)) { + if (sshkeyfile != null && SSHUtil.isEncryptedKey(new File(sshkeyfile))) { sshkeypassphrase = getSSHPassphrase(true); } } @@ -126,7 +124,8 @@ private void copyToHostsInternal(File zipFile, ArrayList binDirFiles) th boolean prompt = promptPass; for (String host : hosts) { - sshLauncher.init(getRemoteUser(), host, getRemotePort(), sshpassword, getSshKeyFile(), sshkeypassphrase, logger); + File keyFile = getSshKeyFile() == null ? null : new File(getSshKeyFile()); + sshLauncher.init(getRemoteUser(), host, getRemotePort(), sshpassword, keyFile, sshkeypassphrase, logger); if (getSshKeyFile() != null && !sshLauncher.checkConnection()) { //key auth failed, so use password auth @@ -135,13 +134,14 @@ private void copyToHostsInternal(File zipFile, ArrayList binDirFiles) th if (prompt) { String sshpass = null; - if (sshPasswords.containsKey(host)) + if (sshPasswords.containsKey(host)) { sshpass = String.valueOf(sshPasswords.get(host)); - else + } else { sshpass = getSSHPassword(host); + } //re-initialize - sshLauncher.init(getRemoteUser(), host, getRemotePort(), sshpass, getSshKeyFile(), sshkeypassphrase, logger); + sshLauncher.init(getRemoteUser(), host, getRemotePort(), sshpass, keyFile, sshkeypassphrase, logger); prompt = false; } @@ -355,9 +355,10 @@ final void precopy() throws CommandException { boolean prompt = promptPass; for (String host : hosts) { - sshLauncher.init(getRemoteUser(), host, getRemotePort(), sshpassword, getSshKeyFile(), sshkeypassphrase, logger); + File keyFile = getSshKeyFile() == null ? null : new File(getSshKeyFile()); + sshLauncher.init(getRemoteUser(), host, getRemotePort(), sshpassword, keyFile, sshkeypassphrase, logger); - if (getSshKeyFile() != null && !sshLauncher.checkConnection()) { + if (keyFile != null && !sshLauncher.checkConnection()) { //key auth failed, so use password auth prompt = true; } @@ -366,7 +367,7 @@ final void precopy() throws CommandException { String sshpass = getSSHPassword(host); sshPasswords.put(host, sshpass.toCharArray()); //re-initialize - sshLauncher.init(getRemoteUser(), host, getRemotePort(), sshpass, getSshKeyFile(), sshkeypassphrase, logger); + sshLauncher.init(getRemoteUser(), host, getRemotePort(), sshpass, keyFile, sshkeypassphrase, logger); prompt = false; } diff --git a/nucleus/cluster/cli/src/main/java/com/sun/enterprise/admin/cli/cluster/NativeRemoteCommandsBase.java b/nucleus/cluster/cli/src/main/java/com/sun/enterprise/admin/cli/cluster/NativeRemoteCommandsBase.java index e118f8f5cb7..6949c426cae 100644 --- a/nucleus/cluster/cli/src/main/java/com/sun/enterprise/admin/cli/cluster/NativeRemoteCommandsBase.java +++ b/nucleus/cluster/cli/src/main/java/com/sun/enterprise/admin/cli/cluster/NativeRemoteCommandsBase.java @@ -1,4 +1,5 @@ /* + * Copyright (c) 2022 Contributors to the Eclipse Foundation * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the @@ -25,11 +26,6 @@ import com.sun.enterprise.util.SystemPropertyConstants; import com.sun.enterprise.util.io.DomainDirs; import com.sun.enterprise.util.io.FileUtils; -import org.glassfish.api.Param; -import org.glassfish.api.admin.CommandException; -import org.glassfish.cluster.ssh.launcher.SSHLauncher; -import org.glassfish.cluster.ssh.sftp.SFTPClient; -import org.glassfish.internal.api.RelativePathResolver; import java.io.File; import java.io.FileFilter; @@ -39,6 +35,12 @@ import java.util.Set; import java.util.logging.Level; +import org.glassfish.api.Param; +import org.glassfish.api.admin.CommandException; +import org.glassfish.cluster.ssh.launcher.SSHLauncher; +import org.glassfish.cluster.ssh.sftp.SFTPClient; +import org.glassfish.internal.api.RelativePathResolver; + /** * Base class for SSH provisioning commands. * @@ -96,8 +98,9 @@ private String getRemotePassword(String node, String key) throws CommandExceptio if (password != null) { String alias = RelativePathResolver.getAlias(password); - if (alias != null) + if (alias != null) { password = expandPasswordAlias(node, alias, true); + } } //get password from user if not found in password file @@ -122,8 +125,9 @@ String getSSHPassphrase(boolean verifyConn) throws CommandException { if (passphrase != null) { String alias = RelativePathResolver.getAlias(passphrase); - if (alias != null) + if (alias != null) { passphrase = expandPasswordAlias(null, alias, verifyConn); + } } //get password from user if not found in password file @@ -196,8 +200,9 @@ else if (directoryEntry.getAttrs().isDir()) { //only if file is present in DAS, it is targeted for removal on remote host //using force deletes all files on remote host if (force) { - if (logger.isLoggable(Level.FINE)) + if (logger.isLoggable(Level.FINE)) { logger.fine("Force removing directory " + f1); + } if (isRemoteDirectoryEmpty(sftpClient, f1)) { sftpClient.getSftpChannel().rmdir(f1); } @@ -213,13 +218,15 @@ else if (directoryEntry.getAttrs().isDir()) { else { String f2 = dir + "/" + directoryEntry.getFilename(); if (force) { - if (logger.isLoggable(Level.FINE)) + if (logger.isLoggable(Level.FINE)) { logger.fine("Force removing file " + f2); + } sftpClient.getSftpChannel().rm(f2); } else { - if (dasFiles.contains(f2)) + if (dasFiles.contains(f2)) { sftpClient.getSftpChannel().rm(f2); + } } } } @@ -234,9 +241,10 @@ else if (directoryEntry.getAttrs().isDir()) { * @throws SftpException */ boolean isRemoteDirectoryEmpty(SFTPClient sftp, String file) throws SftpException { - List l = (List) sftp.getSftpChannel().ls(file); - if (l.size() > 2) + List l = sftp.getSftpChannel().ls(file); + if (l.size() > 2) { return false; + } return true; } @@ -246,8 +254,9 @@ boolean isRemoteDirectoryEmpty(SFTPClient sftp, String file) throws SftpExceptio * @return */ String removeTrailingSlash(String s) { - if (!StringUtils.ok(s)) + if (!StringUtils.ok(s)) { return s; + } if (s.endsWith("/")) { s = s.substring(0, s.length() - 1); @@ -270,6 +279,7 @@ String expandPasswordAlias(String host, String alias, boolean verifyConn) { //get the list of domains File[] files = domainsDirFile.listFiles(new FileFilter() { + @Override public boolean accept(File f) { return f.isDirectory(); } @@ -307,7 +317,8 @@ public boolean accept(File f) { else { sshkeypassphrase = expandedPassword; if (verifyConn) { - sshL.init(getRemoteUser(), hosts[0], getRemotePort(), sshpassword, getSshKeyFile(), sshkeypassphrase, logger); + File keyFile = getSshKeyFile() == null ? null : new File(getSshKeyFile()); + sshL.init(getRemoteUser(), hosts[0], getRemotePort(), sshpassword, keyFile, sshkeypassphrase, logger); connStatus = sshL.checkConnection(); if (!connStatus) { logger.warning(Strings.get("PasswordAuthFailure", f.getName())); @@ -340,14 +351,15 @@ public boolean accept(File f) { List getListOfInstallFiles(String installDir) throws IOException { String ins = resolver.resolve("${com.sun.aas.productRoot}"); Set files = FileUtils.getAllFilesAndDirectoriesUnder(new File(ins)); - if (logger.isLoggable(Level.FINER)) + if (logger.isLoggable(Level.FINER)) { logger.finer("Total number of files under " + ins + " = " + files.size()); + } String remoteDir = installDir; if (!installDir.endsWith("/")) { remoteDir = remoteDir + "/"; } - List modList = new ArrayList(); + List modList = new ArrayList<>(); for (Object f : files) { modList.add(remoteDir + FileUtils.makeForwardSlashes(((File) f).getPath())); } diff --git a/nucleus/cluster/cli/src/main/java/com/sun/enterprise/admin/cli/cluster/SetupSshKey.java b/nucleus/cluster/cli/src/main/java/com/sun/enterprise/admin/cli/cluster/SetupSshKey.java index 6c67811d474..c130f8552f8 100644 --- a/nucleus/cluster/cli/src/main/java/com/sun/enterprise/admin/cli/cluster/SetupSshKey.java +++ b/nucleus/cluster/cli/src/main/java/com/sun/enterprise/admin/cli/cluster/SetupSshKey.java @@ -1,4 +1,5 @@ /* + * Copyright (c) 2022 Contributors to the Eclipse Foundation * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the @@ -16,21 +17,24 @@ package com.sun.enterprise.admin.cli.cluster; -import java.io.*; -import java.util.Arrays; -import java.util.logging.Level; - import jakarta.inject.Inject; +import java.io.Console; +import java.io.File; +import java.io.IOException; +import java.util.Arrays; +import java.util.logging.Level; -import org.jvnet.hk2.annotations.Service; import org.glassfish.api.Param; -import org.glassfish.api.admin.*; +import org.glassfish.api.admin.CommandException; +import org.glassfish.api.admin.ExecuteOn; +import org.glassfish.api.admin.RuntimeType; +import org.glassfish.cluster.ssh.launcher.SSHLauncher; +import org.glassfish.cluster.ssh.util.SSHUtil; import org.glassfish.hk2.api.PerLookup; import org.glassfish.hk2.api.ServiceLocator; import org.glassfish.internal.api.Globals; -import org.glassfish.cluster.ssh.launcher.SSHLauncher; -import org.glassfish.cluster.ssh.util.SSHUtil; +import org.jvnet.hk2.annotations.Service; /** * This is a local command that distributes the SSH public key to remote node(s) @@ -53,65 +57,55 @@ public final class SetupSshKey extends NativeRemoteCommandsBase { @Inject private ServiceLocator habitat; - public SetupSshKey() { - } - /** - */ @Override - protected void validate() - throws CommandException { + protected void validate() throws CommandException { super.validate(); Globals.setDefaultHabitat(habitat); if (sshkeyfile == null) { - //if user hasn't specified a key file and there is no key file at default - //location, then generate one - String existingKey = SSHUtil.getExistingKeyFile(); + // if user hasn't specified a key file and there is no key file at default + // location, then generate one + File existingKey = SSHUtil.getExistingKeyFile(); if (existingKey == null) { - sshkeyfile = SSHUtil.getDefaultKeyFile(); + sshkeyfile = SSHUtil.getDefaultKeyFile().getAbsolutePath(); if (promptForKeyGeneration()) { generatekey = true; } - } - else { - //there is a key that requires to be distributed, hence need password + } else { + // there is a key that requires to be distributed, hence need password promptPass = true; - sshkeyfile = existingKey; - - if (SSHUtil.isEncryptedKey(sshkeyfile)) { + sshkeyfile = existingKey.getAbsolutePath(); + if (SSHUtil.isEncryptedKey(existingKey)) { sshkeypassphrase = getSSHPassphrase(false); } } - } - else { - promptPass = SSHUtil.validateKeyFile(sshkeyfile); - if (SSHUtil.isEncryptedKey(sshkeyfile)) { + } else { + File keyFile = new File(sshkeyfile); + promptPass = SSHUtil.validateKeyFile(keyFile); + if (SSHUtil.isEncryptedKey(new File(sshkeyfile))) { sshkeypassphrase = getSSHPassphrase(false); } } if (sshpublickeyfile != null) { - SSHUtil.validateKeyFile(sshpublickeyfile); + SSHUtil.validateKeyFile(new File(sshpublickeyfile)); } - } - /** - */ - @Override - protected int executeCommand() - throws CommandException { + @Override + protected int executeCommand() throws CommandException { SSHLauncher sshL = habitat.getService(SSHLauncher.class); String previousPassword = null; boolean status = false; for (String node : hosts) { - sshL.init(getRemoteUser(), node, getRemotePort(), sshpassword, sshkeyfile, sshkeypassphrase, logger); + File keyFile = sshkeyfile == null ? null : new File(sshkeyfile); + sshL.init(getRemoteUser(), node, getRemotePort(), sshpassword, keyFile, sshkeypassphrase, logger); if (generatekey || promptPass) { //prompt for password iff required - if (sshkeyfile != null || SSHUtil.getExistingKeyFile() != null) { + if (keyFile != null || SSHUtil.getExistingKeyFile() != null) { if (sshL.checkConnection()) { logger.info(Strings.get("SSHAlreadySetup", getRemoteUser(), node)); continue; @@ -128,16 +122,11 @@ protected int executeCommand() try { sshL.setupKey(node, sshpublickeyfile, generatekey, sshpassword); - } - catch (IOException ce) { - //logger.fine("SSH key setup failed: " + ce.getMessage()); + } catch (IOException ce) { + // logger.fine("SSH key setup failed: " + ce.getMessage()); throw new CommandException(Strings.get("KeySetupFailed", ce.getMessage())); - } - catch (Exception e) { - //handle KeyStoreException - if (logger.isLoggable(Level.FINER)) { - logger.log(Level.FINER, "Keystore error: ", e); - } + } catch (Exception e) { + logger.log(Level.WARNING, "Keystore error for node: " + node, e); } if (!sshL.checkConnection()) { @@ -151,11 +140,13 @@ protected int executeCommand() * Prompt for key generation */ private boolean promptForKeyGeneration() { - if (generatekey) + if (generatekey) { return true; + } - if (!programOpts.isInteractive()) + if (!programOpts.isInteractive()) { return false; + } Console cons = System.console(); @@ -179,8 +170,7 @@ else if (val != null && (val.equalsIgnoreCase("no") || val.equalsIgnoreCase("n") return false; } - @Override - final String getRawRemoteUser() { + @Override String getRawRemoteUser() { return user; } diff --git a/nucleus/cluster/cli/src/main/java/com/sun/enterprise/admin/cli/cluster/SynchronizeInstanceCommand.java b/nucleus/cluster/cli/src/main/java/com/sun/enterprise/admin/cli/cluster/SynchronizeInstanceCommand.java index bd1c616f207..5a26a97d34a 100644 --- a/nucleus/cluster/cli/src/main/java/com/sun/enterprise/admin/cli/cluster/SynchronizeInstanceCommand.java +++ b/nucleus/cluster/cli/src/main/java/com/sun/enterprise/admin/cli/cluster/SynchronizeInstanceCommand.java @@ -26,8 +26,8 @@ import jakarta.xml.bind.Marshaller; import java.io.File; -import java.io.FileOutputStream; import java.io.IOException; +import java.io.InputStream; import java.net.ConnectException; import java.text.DateFormat; import java.util.Date; @@ -466,34 +466,27 @@ private void removeSubdirectory(String name) { */ private static void expand(File dir, File archive) throws Exception { if (!dir.mkdir()) { - logger.warning( - Strings.get("Sync.cantCreateDirectory", dir)); + logger.warning(Strings.get("Sync.cantCreateDirectory", dir)); } long modtime = archive.lastModified(); - ZipFile zf = new ZipFile(archive); - try { + try (ZipFile zf = new ZipFile(archive)) { Enumeration e = zf.entries(); while (e.hasMoreElements()) { ZipEntry ze = e.nextElement(); File entry = new File(dir, ze.getName()); if (ze.isDirectory()) { if (!entry.mkdir()) { - logger.warning( - Strings.get("Sync.cantCreateDirectory", dir)); + logger.warning(Strings.get("Sync.cantCreateDirectory", dir)); } } else { - FileUtils.copy(zf.getInputStream(ze), - new FileOutputStream(entry), 0); + try (InputStream inputStream = zf.getInputStream(ze)) { + FileUtils.copy(inputStream, entry, ze.getSize()); + } } } - } finally { - try { - zf.close(); - } catch (IOException ex) { } } if (!dir.setLastModified(modtime)) { - logger.warning( - Strings.get("Sync.cantSetModTime", dir)); + logger.warning(Strings.get("Sync.cantSetModTime", dir)); } } } diff --git a/nucleus/cluster/cli/src/main/java/com/sun/enterprise/admin/cli/cluster/UninstallNodeSshCommand.java b/nucleus/cluster/cli/src/main/java/com/sun/enterprise/admin/cli/cluster/UninstallNodeSshCommand.java index 97f1f77f938..345937f7922 100644 --- a/nucleus/cluster/cli/src/main/java/com/sun/enterprise/admin/cli/cluster/UninstallNodeSshCommand.java +++ b/nucleus/cluster/cli/src/main/java/com/sun/enterprise/admin/cli/cluster/UninstallNodeSshCommand.java @@ -1,4 +1,5 @@ /* + * Copyright (c) 2022 Contributors to the Eclipse Foundation * Copyright (c) 2011, 2018 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the @@ -16,20 +17,21 @@ package com.sun.enterprise.admin.cli.cluster; +import jakarta.inject.Inject; + +import java.io.File; import java.io.IOException; -import java.util.*; +import java.util.List; + import org.glassfish.api.Param; import org.glassfish.api.admin.CommandException; import org.glassfish.cluster.ssh.launcher.SSHLauncher; import org.glassfish.cluster.ssh.sftp.SFTPClient; import org.glassfish.cluster.ssh.util.SSHUtil; -import jakarta.inject.Inject; - -import org.jvnet.hk2.annotations.Service; import org.glassfish.hk2.api.PerLookup; +import org.jvnet.hk2.annotations.Service; /** - * * @author Byron Nevins */ @Service(name = "uninstall-node-ssh") @@ -63,36 +65,34 @@ String getSshKeyFile() { protected void validate() throws CommandException { super.validate(); if (sshkeyfile == null) { - //if user hasn't specified a key file check if key exists in - //default location - String existingKey = SSHUtil.getExistingKeyFile(); + // if user hasn't specified a key file check if key exists in + // default location + File existingKey = SSHUtil.getExistingKeyFile(); if (existingKey == null) { promptPass = true; + } else { + sshkeyfile = existingKey.getAbsolutePath(); } - else { - sshkeyfile = existingKey; - } - } - else { + } else { validateKey(sshkeyfile); } - //we need the key passphrase if key is encrypted - if (sshkeyfile != null && SSHUtil.isEncryptedKey(sshkeyfile)) { + // we need the key passphrase if key is encrypted + if (sshkeyfile != null && SSHUtil.isEncryptedKey(new File(sshkeyfile))) { sshkeypassphrase = getSSHPassphrase(true); } } @Override void deleteFromHosts() throws CommandException { - SFTPClient sftpClient = null; try { List files = getListOfInstallFiles(getInstallDir()); for (String host : hosts) { - sshLauncher.init(getRemoteUser(), host, getRemotePort(), sshpassword, sshkeyfile, sshkeypassphrase, logger); + File keyFile = sshkeyfile == null ? null : new File(sshkeyfile); + sshLauncher.init(getRemoteUser(), host, getRemotePort(), sshpassword, keyFile, sshkeypassphrase, logger); - if (sshkeyfile != null && !sshLauncher.checkConnection()) { + if (keyFile != null && !sshLauncher.checkConnection()) { //key auth failed, so use password auth promptPass = true; } @@ -100,32 +100,23 @@ void deleteFromHosts() throws CommandException { if (promptPass) { sshpassword = getSSHPassword(host); //re-initialize - sshLauncher.init(getRemoteUser(), host, getRemotePort(), sshpassword, sshkeyfile, sshkeypassphrase, logger); - } - - sftpClient = sshLauncher.getSFTPClient(); - - if (!sftpClient.exists(getInstallDir())) { - throw new IOException(getInstallDir() + " Directory does not exist"); + sshLauncher.init(getRemoteUser(), host, getRemotePort(), sshpassword, keyFile, sshkeypassphrase, logger); } - deleteRemoteFiles(sftpClient, files, getInstallDir(), getForce()); - - if (isRemoteDirectoryEmpty(sftpClient, getInstallDir())) { - sftpClient.getSftpChannel().rmdir(getInstallDir()); + try (SFTPClient sftpClient = sshLauncher.getSFTPClient()) { + if (!sftpClient.exists(getInstallDir())) { + throw new IOException(getInstallDir() + " Directory does not exist"); + } + deleteRemoteFiles(sftpClient, files, getInstallDir(), getForce()); + if (isRemoteDirectoryEmpty(sftpClient, getInstallDir())) { + sftpClient.getSftpChannel().rmdir(getInstallDir()); + } } - sftpClient.close(); } - } - catch (CommandException ce) { + } catch (CommandException ce) { throw ce; - } - catch (Exception ex) { + } catch (Exception ex) { throw new CommandException(ex); - } finally { - if (sftpClient != null) { - sftpClient.close(); - } } } } diff --git a/nucleus/cluster/ssh/src/main/java/org/glassfish/cluster/ssh/launcher/SSHLauncher.java b/nucleus/cluster/ssh/src/main/java/org/glassfish/cluster/ssh/launcher/SSHLauncher.java index fc478b95d0d..6f16daffa14 100644 --- a/nucleus/cluster/ssh/src/main/java/org/glassfish/cluster/ssh/launcher/SSHLauncher.java +++ b/nucleus/cluster/ssh/src/main/java/org/glassfish/cluster/ssh/launcher/SSHLauncher.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 Contributors to the Eclipse Foundation + * Copyright (c) 2022, 2023 Contributors to the Eclipse Foundation * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the @@ -32,29 +32,35 @@ import com.sun.enterprise.util.OS; import com.sun.enterprise.util.StringUtils; import com.sun.enterprise.util.io.FileUtils; -import org.glassfish.cluster.ssh.sftp.SFTPClient; -import org.glassfish.cluster.ssh.util.SSHUtil; -import org.glassfish.hk2.api.PerLookup; -import org.glassfish.internal.api.RelativePathResolver; -import org.jvnet.hk2.annotations.Service; -import java.io.*; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.nio.file.Path; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; +import org.glassfish.cluster.ssh.sftp.SFTPClient; +import org.glassfish.cluster.ssh.util.SSHUtil; +import org.glassfish.hk2.api.PerLookup; +import org.glassfish.internal.api.RelativePathResolver; +import org.jvnet.hk2.annotations.Service; + /** * @author Rajiv Mordani, Krishna Deepak */ - - @Service(name="SSHLauncher") @PerLookup public class SSHLauncher { - private static final String SSH_DIR = ".ssh" + File.separator; + private static final String SSH_DIR_NAME = ".ssh"; private static final String AUTH_KEY_FILE = "authorized_keys"; private static final int DEFAULT_TIMEOUT_MSEC = 120000; // 2 minutes private static final String SSH_KEYGEN = "ssh-keygen"; @@ -78,7 +84,7 @@ public class SSHLauncher { /** * The name of private key file. */ - private String keyFile; + private File keyFile; /** * The connection object that represents the connection to the host @@ -128,14 +134,15 @@ public void init(Node node, Logger logger) { //XXX Why do we need this again? This is already done above and set to host String sshHost = connector.getSshHost(); - if (sshHost != null) + if (sshHost != null) { this.host = sshHost; + } SshAuth sshAuth = connector.getSshAuth(); String userName = null; if (sshAuth != null) { userName = sshAuth.getUserName(); - this.keyFile = sshAuth.getKeyfile(); + this.keyFile = new File(sshAuth.getKeyfile()); this.rawPassword = sshAuth.getPassword(); this.rawKeyPassPhrase = sshAuth.getKeyPassphrase(); } @@ -160,71 +167,56 @@ public void init(Node node, Logger logger) { * @param keyPassPhrase * @param logger */ - public void init(String userName, String host, int port, String password, String keyFile, String keyPassPhrase, Logger logger) { + public void init(String userName, String host, int port, String password, File keyFile, String keyPassPhrase, Logger logger) { this.port = port == 0 ? 22 : port; this.host = host; - this.keyFile = (keyFile == null) ? SSHUtil.getExistingKeyFile(): keyFile; + this.keyFile = keyFile == null ? SSHUtil.getExistingKeyFile(): keyFile; this.logger = logger; - - this.userName = SSHUtil.checkString(userName) == null ? - System.getProperty("user.name") : userName; - - + this.userName = SSHUtil.checkString(userName) == null ? System.getProperty("user.name") : userName; this.rawPassword = password; this.password = expandPasswordAlias(password); this.rawKeyPassPhrase = keyPassPhrase; this.keyPassPhrase = expandPasswordAlias(keyPassPhrase); - File home = new File(System.getProperty("user.home")); - File knownHosts = new File(home,".ssh/known_hosts"); + File knownHosts = FileUtils.USER_HOME.toPath().resolve(Path.of(SSH_DIR_NAME, "known_hosts")).toFile(); if (knownHosts.exists()) { knownHostsLocation = knownHosts.getAbsolutePath(); } - if (logger.isLoggable(Level.FINER)) { - logger.finer("SSH info is " + toString()); - } + logger.log(Level.FINER, "SSH info is {0}", this); } - /** - * - */ private void openConnection() throws JSchException { assert session == null; JSch jsch = new JSch(); - jsch.setLogger(new JavaSystemJschLogger(logger != null ? logger.getName() + ".ssh" : JSch.class.getName())); + JSch.setLogger(new JavaSystemJschLogger(logger != null ? logger.getName() + ".ssh" : JSch.class.getName())); // Client Auth String message = ""; boolean triedAuthentication = false; // Private key file is provided - Public Key Authentication - if (SSHUtil.checkString(keyFile) != null) { + if (keyFile != null) { if (logger.isLoggable(Level.FINER)) { logger.finer("Specified key file is " + keyFile); } - File key = new File(keyFile); - if (key.exists()) { + if (keyFile.exists()) { triedAuthentication = true; if (logger.isLoggable(Level.FINER)) { - logger.finer("Specified key file exists at " + key); + logger.finer("Specified key file exists at " + keyFile); } - jsch.addIdentity(key.getAbsolutePath(), keyPassPhrase); - } - else { + jsch.addIdentity(keyFile.getAbsolutePath(), keyPassPhrase); + } else { message = "Specified key file does not exist \n"; } - } - else if(SSHUtil.checkString(password) == null) { + } else if (SSHUtil.checkString(password) == null) { message += "No key or password specified - trying default keys \n"; - if (logger.isLoggable(Level.FINE)) { - logger.fine("keyfile and password are null. Will try to authenticate with default key file if available"); - } + logger.fine("keyfile and password are null. Will try to authenticate with default key file if available"); // check the default key locations if no authentication // method is explicitly configured. - File home = new File(System.getProperty("user.home")); + Path home = FileUtils.USER_HOME.toPath(); for (String keyName : Arrays.asList("id_rsa", "id_dsa", "identity")) { message += "Tried to authenticate using " + keyName + "\n"; - File key = new File(home, ".ssh/" + keyName); + File key = home.resolve(Path.of(SSH_DIR_NAME, keyName)).toFile(); if (key.exists()) { triedAuthentication = true; jsch.addIdentity(key.getAbsolutePath()); @@ -341,10 +333,12 @@ private int runCommandAsIs(String command, OutputStream os, logger.finer("Running command " + command + " on host: " + this.host); } boolean createNewSession = false; - if (session == null) + if (session == null) { createNewSession = true; - if(createNewSession) + } + if(createNewSession) { openConnection(); + } int status = exec(command, os, listInputStream(stdinLines)); @@ -424,6 +418,7 @@ public PumpThread(InputStream in, OutputStream out) { this.out = out; } + @Override public void run() { byte[] buf = new byte[1024]; try { @@ -449,18 +444,19 @@ public void pingConnection() throws JSchException, InterruptedException session = null; } - /* validate user provided ars - * check connecton to host - * check that the install dir is correct - * landmarkPath must be relative to the installdir - */ + /** + * Validate user provided args. + * Check connecton to host. + * Check that the install dir is correct + * + * @param landmarkPath must be relative to the installdir + */ public void validate(String host, int port, - String userName, String password, - String keyFile, String keyPassPhrase, - String installDir, String landmarkPath, - Logger logger) throws IOException - { + String userName, String password, + File keyFile, String keyPassPhrase, + String installDir, String landmarkPath, + Logger logger) throws IOException { boolean validInstallDir = false; init(userName, host, port, password, keyFile, keyPassPhrase, logger); @@ -497,15 +493,6 @@ public void validate(String host, int port, } } - public void validate(String host, int port, - String userName, String password, - String keyFile, String keyPassPhrase, - String installDir, Logger logger) throws IOException - { - // Validate with no landmark file - validate(host, port, userName, password, keyFile, keyPassPhrase, - installDir, null, logger); - } public SFTPClient getSFTPClient() throws JSchException { openConnection(); @@ -523,7 +510,7 @@ public String expandPasswordAlias(String alias) { try { expandedPassword = RelativePathResolver.getRealPasswordFromAlias(alias); } catch (Exception e) { - logger.warning(StringUtils.cat(": ", alias, e.getMessage())); + logger.log(Level.WARNING, "Expansion failed for {0}: {1}", new Object[] {alias, e.getMessage()}); return null; } @@ -573,12 +560,12 @@ private String getPrintablePassword(String p) { * @throws InterruptedException */ public void setupKey(String node, String pubKeyFile, boolean generateKey, String passwd) - throws IOException, InterruptedException { - boolean connected = false; + throws IOException, InterruptedException { - File key = new File(keyFile); - if(logger.isLoggable(Level.FINER)) + File key = keyFile; + if (logger.isLoggable(Level.FINER)) { logger.finer("Key = " + keyFile); + } if (key.exists()) { if (checkConnection()) { throw new IOException("SSH public key authentication is already configured for " + userName + "@" + node); @@ -607,92 +594,85 @@ public void setupKey(String node, String pubKeyFile, boolean generateKey, String if (!s1.isConnected()) { throw new IOException("SSH password authentication failed for user " + userName + " on host " + node); } - SFTPClient sftp = new SFTPClient(s1); - ChannelSftp sftpChannel = sftp.getSftpChannel(); + try (SFTPClient sftp = new SFTPClient(s1)) { + ChannelSftp sftpChannel = sftp.getSftpChannel(); - this.session = s1; + this.session = s1; - if (key.exists()) { + if (key.exists()) { - //fixes .ssh file mode - setupSSHDir(); + // fixes .ssh file mode + setupSSHDir(); - if (pubKeyFile == null) { - pubKeyFile = keyFile + ".pub"; - } + if (pubKeyFile == null) { + pubKeyFile = keyFile + ".pub"; + } - File pubKey = new File(pubKeyFile); - if (!pubKey.exists()) { - throw new IOException("Public key file " + pubKeyFile + " does not exist."); - } + File pubKey = new File(pubKeyFile); + if (!pubKey.exists()) { + throw new IOException("Public key file " + pubKeyFile + " does not exist."); + } - try { - if (!sftp.exists(SSH_DIR)) { - if (logger.isLoggable(Level.FINE)) { - logger.fine(SSH_DIR + " does not exist"); + try { + if (!sftp.exists(SSH_DIR_NAME)) { + logger.fine(SSH_DIR_NAME + " does not exist"); + sftpChannel.cd(sftpChannel.getHome()); + sftpChannel.mkdir(SSH_DIR_NAME); + sftpChannel.chmod(0700, SSH_DIR_NAME); } - sftpChannel.cd(sftpChannel.getHome()); - sftpChannel.mkdir(".ssh"); - sftpChannel.chmod(0700, ".ssh"); - } - } catch (Exception e) { - if (logger.isLoggable(Level.FINER)) { - e.printStackTrace(); + } catch (Exception e) { + throw new IOException("Error while creating .ssh directory on remote host: " + e.getMessage(), e); } - throw new IOException("Error while creating .ssh directory on remote host:" + e.getMessage()); - } - //copy over the public key to remote host - //scp.put(pubKey.getAbsolutePath(), "key.tmp", ".ssh", "0600"); - try { - sftpChannel.cd(".ssh"); - sftpChannel.put(pubKey.getAbsolutePath(), "key.tmp"); - sftpChannel.chmod(0600, "key.tmp"); - } catch (SftpException ex) { - throw new IOException("Unable to copy the public key", ex); - } + // copy over the public key to remote host + // scp.put(pubKey.getAbsolutePath(), "key.tmp", ".ssh", "0600"); + try { + sftpChannel.cd(SSH_DIR_NAME); + sftpChannel.put(pubKey.getAbsolutePath(), "key.tmp"); + sftpChannel.chmod(0600, "key.tmp"); + } catch (SftpException ex) { + throw new IOException("Unable to copy the public key", ex); + } - //append the public key file contents to authorized_keys file on remote host - String mergeCommand = "cd .ssh; cat key.tmp >> " + AUTH_KEY_FILE; - if (logger.isLoggable(Level.FINER)) { - logger.finer("mergeCommand = " + mergeCommand); - } - if (exec(mergeCommand, new ByteArrayOutputStream()) != 0) { - throw new IOException("Failed to propogate the public key " + pubKeyFile + " to " + host); - } - logger.info("Copied keyfile " + pubKeyFile + " to " + userName + "@" + host); + // append the public key file contents to authorized_keys file on remote host + String mergeCommand = "cd .ssh; cat key.tmp >> " + AUTH_KEY_FILE; + if (logger.isLoggable(Level.FINER)) { + logger.finer("mergeCommand = " + mergeCommand); + } + if (exec(mergeCommand, new ByteArrayOutputStream()) != 0) { + throw new IOException("Failed to propogate the public key " + pubKeyFile + " to " + host); + } + logger.info("Copied keyfile " + pubKeyFile + " to " + userName + "@" + host); - //remove the public key file on remote host - if (exec("rm .ssh/key.tmp", new ByteArrayOutputStream()) != 0) { - logger.warning("WARNING: Failed to remove the public key file key.tmp on remote host " + host); - } - if (logger.isLoggable(Level.FINER)) { - logger.finer("Removed the temporary key file on remote host"); - } + // remove the public key file on remote host + if (exec("rm .ssh/key.tmp", new ByteArrayOutputStream()) != 0) { + logger.warning("WARNING: Failed to remove the public key file key.tmp on remote host " + host); + } + if (logger.isLoggable(Level.FINER)) { + logger.finer("Removed the temporary key file on remote host"); + } - //Lets fix all the permissions - //On MKS, chmod doesn't work as expected. StrictMode needs to be disabled - //for connection to go through - logger.info("Fixing file permissions for home(755), .ssh(700) and authorized_keys file(644)"); - try { - sftpChannel.cd(sftpChannel.getHome()); - sftpChannel.chmod(0755, "."); - sftpChannel.chmod(0700, ".ssh"); - sftpChannel.chmod(0644, SSH_DIR + AUTH_KEY_FILE); - } catch (SftpException ex) { - throw new IOException("Unable to fix file permissions", ex); + // Lets fix all the permissions + // On MKS, chmod doesn't work as expected. StrictMode needs to be disabled + // for connection to go through + logger.info("Fixing file permissions for home(755), .ssh(700) and authorized_keys file(644)"); + try { + sftpChannel.cd(sftpChannel.getHome()); + sftpChannel.chmod(0755, "."); + sftpChannel.chmod(0700, SSH_DIR_NAME); + sftpChannel.chmod(0644, SSH_DIR_NAME + "/" + AUTH_KEY_FILE); + } catch (SftpException ex) { + throw new IOException("Unable to fix file permissions", ex); + } } - //release the connections - sftp.close(); } } catch (JSchException ex) { throw new IOException(ex); } } - public static byte[] toByteArray( InputStream input ) - throws IOException - { + + public static byte[] toByteArray(InputStream input) throws IOException { ByteArrayOutputStream output = new ByteArrayOutputStream(); byte[] buf = new byte[4096]; int len; @@ -714,11 +694,8 @@ public boolean checkConnection() { Session sess = null; try { - File f = new File(keyFile); - if(logger.isLoggable(Level.FINER)) { - logger.finer("Checking connection..."); - } - jsch.addIdentity(f.getAbsolutePath(), rawKeyPassPhrase); + logger.finer("Checking connection..."); + jsch.addIdentity(keyFile.getAbsolutePath(), rawKeyPassPhrase); sess = jsch.getSession(userName, host, port); sess.setConfig("StrictHostKeyChecking", "no"); sess.connect(); @@ -737,8 +714,9 @@ public boolean checkConnection() { logger.log(Level.FINER, "Failed to connect or autheticate: ", ex); } } finally { - if (sess != null) + if (sess != null) { sess.disconnect(); + } } return status; } @@ -777,8 +755,9 @@ public boolean checkPasswordAuth() { logger.log(Level.FINER, "Failed to connect or autheticate: ", ex); } } finally { - if (sess != null) + if (sess != null) { sess.disconnect(); + } } return status; } @@ -797,7 +776,7 @@ private boolean generateKeyPair() throws IOException { } StringBuffer k = new StringBuffer(); - List cmdLine = new ArrayList(); + List cmdLine = new ArrayList<>(); cmdLine.add(keygenCmd); k.append(keygenCmd); cmdLine.add("-t"); @@ -822,7 +801,7 @@ private boolean generateKeyPair() throws IOException { } cmdLine.add("-f"); k.append(" ").append("-f"); - cmdLine.add(keyFile); + cmdLine.add(keyFile.getAbsolutePath()); k.append(" ").append(keyFile); //cmdLine.add("-vvv"); @@ -833,10 +812,11 @@ private boolean generateKeyPair() throws IOException { } pm.setTimeoutMsec(DEFAULT_TIMEOUT_MSEC); - if (logger.isLoggable(Level.FINER)) + if (logger.isLoggable(Level.FINER)) { pm.setEcho(true); - else + } else { pm.setEcho(false); + } int exit; try { @@ -866,7 +846,7 @@ private boolean generateKeyPair() throws IOException { * @return ssh-keygen command */ private String findSSHKeygen() { - List paths = new ArrayList(Arrays.asList( + List paths = new ArrayList<>(Arrays.asList( "/usr/bin/", "/usr/local/bin/")); @@ -902,14 +882,12 @@ private String findSSHKeygen() { */ private boolean setupSSHDir() throws IOException { boolean ret = true; - File home = new File(System.getProperty("user.home")); - File f = new File(home, SSH_DIR); - - if(!FileUtils.safeIsDirectory(f)) { + File f = new File(FileUtils.USER_HOME, SSH_DIR_NAME); + if (!FileUtils.safeIsDirectory(f)) { if (!f.mkdirs()) { throw new IOException("Failed to create " + f.getPath()); } - logger.info("Created directory " + f.toString()); + logger.log(Level.INFO, "Created directory {0}", f); } if (!f.setReadable(false, false) || !f.setReadable(true)) { @@ -924,9 +902,7 @@ private boolean setupSSHDir() throws IOException { ret = false; } - if(logger.isLoggable(Level.FINER)) { - logger.finer("Fixed the .ssh directory permissions to 0700"); - } + logger.finer("Fixed the .ssh directory permissions to 0700"); return ret; } @@ -950,7 +926,9 @@ public String toString() { * @return */ private static String commandListToQuotedString(List command) { - if(command.size()==1) return command.get(0); + if(command.size()==1) { + return command.get(0); + } StringBuilder commandBuilder = new StringBuilder(); boolean first = true; diff --git a/nucleus/cluster/ssh/src/main/java/org/glassfish/cluster/ssh/util/SSHUtil.java b/nucleus/cluster/ssh/src/main/java/org/glassfish/cluster/ssh/util/SSHUtil.java index 3d6a9fee080..05785fbad72 100644 --- a/nucleus/cluster/ssh/src/main/java/org/glassfish/cluster/ssh/util/SSHUtil.java +++ b/nucleus/cluster/ssh/src/main/java/org/glassfish/cluster/ssh/util/SSHUtil.java @@ -1,4 +1,5 @@ /* + * Copyright (c) 2022 Contributors to the Eclipse Foundation * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the @@ -24,73 +25,78 @@ import java.io.File; import java.io.IOException; +import java.nio.file.Path; import com.sun.enterprise.util.io.FileUtils; import org.glassfish.api.admin.CommandException; + /** * @author Rajiv Mordani */ public class SSHUtil { - private static final List activeConnections = new ArrayList(); - private static final String NL = System.getProperty("line.separator"); - - /** - * Registers a connection for cleanup when the plugin is stopped. - * - * @param session The connection. - */ - public static synchronized void register(Session session) { - if (!activeConnections.contains(session)) { - activeConnections.add(session); - } - } - - /** - * Unregisters a connection for cleanup when the plugin is stopped. - * - * @param session The connection. - */ - public static synchronized void unregister(Session session) { - session.disconnect(); - activeConnections.remove(session); - } - - /** - * Convert empty string to null. - */ - public static String checkString(String s) { - if(s==null || s.length()==0) return null; - return s; - } - - public static String getExistingKeyFile() { - String key = null; - for (String keyName : Arrays.asList("id_rsa","id_dsa", - "identity")) - { - String h = System.getProperty("user.home") + File.separator; - File f = new File(h+".ssh"+File.separator+keyName); + + private static final List activeConnections = new ArrayList<>(); + private static final String NL = System.lineSeparator(); + + /** + * Registers a connection for cleanup when the plugin is stopped. + * + * @param session The connection. + */ + public static synchronized void register(Session session) { + if (!activeConnections.contains(session)) { + activeConnections.add(session); + } + } + + + /** + * Unregisters a connection for cleanup when the plugin is stopped. + * + * @param session The connection. + */ + public static synchronized void unregister(Session session) { + session.disconnect(); + activeConnections.remove(session); + } + + + /** + * Convert empty string to null. + */ + public static String checkString(String s) { + if (s == null || s.isEmpty()) { + return null; + } + return s; + } + + + /** + * @return null or id_rsa/id_dsa/identity at user's home directory + */ + public static File getExistingKeyFile() { + Path h = FileUtils.USER_HOME.toPath(); + for (String keyName : Arrays.asList("id_rsa", "id_dsa", "identity")) { + File f = h.resolve(Path.of(".ssh", keyName)).toFile(); if (f.exists()) { - key = h + ".ssh"+File.separator + keyName; - break; + return f; } } - return key; - } + return null; + } - public static String getDefaultKeyFile() { - String k = System.getProperty("user.home") + File.separator - //String k = System.getenv("HOME") + File.separator - + ".ssh" + File.separator + "id_rsa"; - return k; - } + + public static File getDefaultKeyFile() { + return FileUtils.USER_HOME.toPath().resolve(Path.of(".ssh", "id_rsa")).toFile(); + } /** * Simple method to validate an encrypted key file * @return true|false * @throws CommandException */ - public static boolean isEncryptedKey(String keyFile) throws CommandException { + public static boolean isEncryptedKey(File keyFile) throws CommandException { boolean res = false; try { String f = FileUtils.readSmallFile(keyFile); @@ -100,7 +106,7 @@ public static boolean isEncryptedKey(String keyFile) throws CommandException { } } catch (IOException ioe) { - throw new CommandException(Strings.get("error.parsing.key", keyFile, ioe.getMessage())); + throw new CommandException(Strings.get("error.parsing.key", keyFile, ioe.getMessage()), ioe); } return res; } @@ -112,28 +118,21 @@ public static boolean isEncryptedKey(String keyFile) throws CommandException { * @param file the key file * @return success if file exists, false otherwise */ - public static boolean validateKeyFile(String file) throws CommandException { - boolean ret = false; - //if key exists, set prompt flag - File f = new File(file); - if (f.exists()) { - if (!f.getName().endsWith(".pub")) { - String key = null; - try { - key = FileUtils.readSmallFile(file); - } - catch (IOException ioe) { - throw new CommandException(Strings.get("unable.to.read.key", file, ioe.getMessage())); - } - if (!key.startsWith("-----BEGIN ") && !key.endsWith(" PRIVATE KEY-----" + NL)) { - throw new CommandException(Strings.get("invalid.key.file", file)); - } - } - ret = true; - } - else { + public static boolean validateKeyFile(File file) throws CommandException { + if (!file.exists()) { throw new CommandException(Strings.get("key.does.not.exist", file)); } - return ret; + if (!file.getName().endsWith(".pub")) { + String key = null; + try { + key = FileUtils.readSmallFile(file); + } catch (IOException ioe) { + throw new CommandException(Strings.get("unable.to.read.key", file, ioe.getMessage())); + } + if (!key.startsWith("-----BEGIN ") && !key.endsWith(" PRIVATE KEY-----" + NL)) { + throw new CommandException(Strings.get("invalid.key.file", file)); + } + } + return true; } } diff --git a/nucleus/common/amx-core/src/main/java/org/glassfish/admin/amx/util/AMXDebug.java b/nucleus/common/amx-core/src/main/java/org/glassfish/admin/amx/util/AMXDebug.java index c294072840f..92df4e62856 100644 --- a/nucleus/common/amx-core/src/main/java/org/glassfish/admin/amx/util/AMXDebug.java +++ b/nucleus/common/amx-core/src/main/java/org/glassfish/admin/amx/util/AMXDebug.java @@ -1,4 +1,5 @@ /* + * Copyright (c) 2022 Contributors to the Eclipse Foundation * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the @@ -16,6 +17,8 @@ package org.glassfish.admin.amx.util; +import com.sun.enterprise.util.io.FileUtils; + import java.io.File; import java.util.HashSet; import java.util.Set; @@ -167,7 +170,7 @@ public final class AMXDebug private AMXDebug() { - ILLEGAL_CHARS = new HashSet(); + ILLEGAL_CHARS = new HashSet<>(); for (final char c : ILLEGAL_CHARS_ARRAY) { ILLEGAL_CHARS.add(c); @@ -191,7 +194,7 @@ private AMXDebug() value = System.getProperty(AMX_DEBUG_APPEND_SPROP); mAppend = (value != null) && Boolean.parseBoolean(value); - mOutputs = new ConcurrentHashMap(); + mOutputs = new ConcurrentHashMap<>(); mDir = getDir(); mMadeDebugDir = false; @@ -257,9 +260,7 @@ private File getDir() if (value == null) { final String instanceRoot = System.getProperty("com.sun.aas.instanceRoot"); - - File parentDir = instanceRoot != null ? - new File(instanceRoot) : new File(System.getProperty("user.home")); + File parentDir = instanceRoot != null ? new File(instanceRoot) : FileUtils.USER_HOME; debugDir = new File(parentDir, AMX_DEBUG_SUBDIR); } else diff --git a/nucleus/common/common-util/src/main/java/com/sun/enterprise/universal/io/SmartFile.java b/nucleus/common/common-util/src/main/java/com/sun/enterprise/universal/io/SmartFile.java index 7f086115ac4..89ac60facd9 100644 --- a/nucleus/common/common-util/src/main/java/com/sun/enterprise/universal/io/SmartFile.java +++ b/nucleus/common/common-util/src/main/java/com/sun/enterprise/universal/io/SmartFile.java @@ -1,4 +1,5 @@ /* + * Copyright (c) 2022 Contributors to the Eclipse Foundation * Copyright (c) 2008, 2018 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the @@ -16,13 +17,15 @@ package com.sun.enterprise.universal.io; -import java.io.*; -import java.util.*; -import java.util.logging.Level; -import java.util.logging.Logger; - -import com.sun.enterprise.util.StringUtils; import com.sun.enterprise.universal.glassfish.GFLauncherUtils; +import com.sun.enterprise.util.StringUtils; + +import java.io.File; +import java.io.IOException; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Set; /** * A class for sanitizing Files. @@ -77,37 +80,41 @@ public static String sanitize(String filename) { * @return The sanitized paths */ public static String sanitizePaths(String pathsString) { - if (!ok(pathsString)) + if (!ok(pathsString)) { return pathsString; + } try { String[] paths = pathsString.split(File.pathSeparator); StringBuilder sb = new StringBuilder(); - Set pathsSet = new HashSet(); - List pathsList = new LinkedList(); + Set pathsSet = new HashSet<>(); + List pathsList = new LinkedList<>(); - for (int i = 0; i < paths.length; i++) { - String path = paths[i]; + for (String path2 : paths) { + String path = path2; // ignore empty path elements. E.g. "c:/foo;;;;;;;" should become "C:/foo" // not "c:/foo;thisdir;thisdir;thisdir etc" - if (!ok(path)) + if (!ok(path)) { continue; + } // pathsSet is only here for removing duplicates. We need the // List to maintain the original order! path = SmartFile.sanitize(path); - if (pathsSet.add(path)) + if (pathsSet.add(path)) { pathsList.add(path); + } } boolean firstElement = true; for (String path : pathsList) { - if (firstElement) + if (firstElement) { firstElement = false; - else + } else { sb.append(File.pathSeparator); + } sb.append(path); } @@ -119,15 +126,17 @@ public static String sanitizePaths(String pathsString) { } private SmartFile(File f) { - if (f == null) + if (f == null) { throw new NullPointerException(); + } convert(f.getAbsolutePath()); } private SmartFile(String s) { - if (s == null) + if (s == null) { throw new NullPointerException(); + } // note that "" is a valid filename // IT 7500 get rid of quotes!!! @@ -136,10 +145,11 @@ private SmartFile(String s) { } private void convert(String oldPath) { - if (GFLauncherUtils.isWindows()) + if (GFLauncherUtils.isWindows()) { convertWindows(oldPath); - else + } else { convertNix(oldPath); + } } /* @@ -149,8 +159,9 @@ private void convert(String oldPath) { private void convertWindows(String oldPath) { try { path = new File(oldPath).getCanonicalPath(); - if (!path.startsWith("\\")) // network address... + if (!path.startsWith("\\")) { // network address... path = path.replace('\\', '/'); + } } catch (IOException ex) { // what to do? This has never happened to me and I use File I/O @@ -170,9 +181,10 @@ private void convertNix(String oldPath) { ((from + 3 < p.length && p[from+1] == '.' && p[from+2] == '.' && p[from+3] == '/') || (from + 3 == p.length && - p[from+1] == '.' && p[from+2] == '.'))) { + p[from+1] == '.' && p[from+2] == '.'))) { // remove the previous directory due to /../ - while (to > 0 && p[--to] != '/'); + while (to > 0 && p[--to] != '/') { + } from += 2; } else if (p[from] == '/' && @@ -187,7 +199,9 @@ else if (p[from] == '/' && p[to++] = p[from]; } } - if (to > 0 && p[to-1] == '/') to -= 1; + if (to > 0 && p[to-1] == '/') { + to -= 1; + } path = new String(p, 0, to); } diff --git a/nucleus/common/common-util/src/main/java/com/sun/enterprise/util/CULoggerInfo.java b/nucleus/common/common-util/src/main/java/com/sun/enterprise/util/CULoggerInfo.java index fe799e2638d..565f67cd7fa 100644 --- a/nucleus/common/common-util/src/main/java/com/sun/enterprise/util/CULoggerInfo.java +++ b/nucleus/common/common-util/src/main/java/com/sun/enterprise/util/CULoggerInfo.java @@ -54,6 +54,13 @@ public static String getString(String key, Object... args) { return MessageFormat.format(getString(key), args); } + @LogMessageInfo( + message = "Some IOException occurred", + cause = "An unexpected exception occurred.", + action = "Check the system logs and contact Oracle support.", + level = "SEVERE") + public static final String exceptionIO = LOGMSG_PREFIX + "-00031"; + @LogMessageInfo( message = "Failed to process class {0} with bytecode preprocessor {1}", cause = "Unknown", @@ -232,43 +239,6 @@ public static String getString(String key, Object... args) { level = "WARNING") public static final String exceptionWhileFormating = LOGMSG_PREFIX + "-00030"; - @LogMessageInfo( - message = "Some IOException occurred", - cause = "An unexpected exception occurred.", - action = "Check the system logs and contact support.", - level = "SEVERE") - public static final String exceptionIO = LOGMSG_PREFIX + "-00031"; - - @LogMessageInfo( - message = "Attempt to delete {0} failed; the file is reported as non-existent", - level = "FINE") - public static final String deleteFailedAbsent = LOGMSG_PREFIX + "-00032"; - - @LogMessageInfo( - message = "Error attempting to delete {0}", - level = "FINE") - public static final String deleteFailed = LOGMSG_PREFIX + "-00033"; - - @LogMessageInfo( - message = "Performing gc to try to force file closures", - level = "FINE") - public static final String performGC = LOGMSG_PREFIX + "-00034"; - - @LogMessageInfo( - message = "Attempt to rename {0} to {1} succeeded after {2} retries", - level = "FINE") - public static final String retryRenameSuccess = LOGMSG_PREFIX + "-00035"; - - @LogMessageInfo( - message = "Attempt to rename {0} to {1} succeeded without any retries", - level = "FINE") - public static final String renameInitialSuccess = LOGMSG_PREFIX + "-00036"; - - @LogMessageInfo( - message = "Attempt to rename {0} to {1} failed after {2} retries", - level = "WARNING") - public static final String retryRenameFailure = LOGMSG_PREFIX + "-00037"; - @LogMessageInfo( message = "Failed to open jar file: {0}", level = "WARNING") diff --git a/nucleus/common/common-util/src/main/java/com/sun/enterprise/util/io/FileUtils.java b/nucleus/common/common-util/src/main/java/com/sun/enterprise/util/io/FileUtils.java index 0de48f1d075..1b075775250 100644 --- a/nucleus/common/common-util/src/main/java/com/sun/enterprise/util/io/FileUtils.java +++ b/nucleus/common/common-util/src/main/java/com/sun/enterprise/util/io/FileUtils.java @@ -18,18 +18,13 @@ package com.sun.enterprise.util.io; import com.sun.enterprise.universal.i18n.LocalStringsImpl; -import com.sun.enterprise.universal.io.SmartFile; -import com.sun.enterprise.util.CULoggerInfo; import com.sun.enterprise.util.OS; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.BufferedReader; -import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileFilter; -import java.io.FileInputStream; -import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.FileReader; import java.io.FilenameFilter; @@ -37,7 +32,6 @@ import java.io.InputStream; import java.io.OutputStream; import java.io.PrintWriter; -import java.io.RandomAccessFile; import java.io.Writer; import java.lang.System.Logger; import java.lang.System.Logger.Level; @@ -46,45 +40,41 @@ import java.nio.channels.FileChannel; import java.nio.channels.ReadableByteChannel; import java.nio.channels.WritableByteChannel; - -import java.util.ArrayList; +import java.nio.file.Files; import java.util.Collection; -import java.util.List; import java.util.Locale; import java.util.Set; import java.util.TreeSet; import java.util.regex.Pattern; +import org.glassfish.api.deployment.archive.WritableArchiveEntry; + import static java.lang.System.Logger.Level.DEBUG; -import static java.lang.System.Logger.Level.TRACE; import static java.lang.System.Logger.Level.WARNING; -public class FileUtils { +public final class FileUtils { + /** Current user's home directory resolved from the system property user.home */ public static final File USER_HOME = new File(System.getProperty("user.home")); private static final Logger LOG = System.getLogger(FileUtils.class.getName()); - private final static LocalStringsImpl messages = new LocalStringsImpl(FileUtils.class); + private static final LocalStringsImpl I18N = new LocalStringsImpl(FileUtils.class); - /** - * The method, java.io.File.getParentFile() does not necessarily do what - * you would think it does. What it really does is to simply chop off the - * final element in the path and return what is left-over. E.g. - * if the file is /foo/. then the "parent" that is returned is /foo - * which is probably not what you expected. - * This method really returns the parent directory - or null if there is none. - * @param f - * @return - */ - public static File getParentFile(File f) { - if (f == null) { - return null; - } + private static final char[] ILLEGAL_FILENAME_CHARS = {'/', '\\', ':', '*', '?', '"', '<', '>', '|'}; + private static final char REPLACEMENT_CHAR = '_'; + private static final char BLANK = ' '; + private static final char DOT = '.'; - return SmartFile.sanitize(f).getParentFile(); + private static final int FILE_OPERATION_MAX_RETRIES = Integer.getInteger("com.sun.appserv.winFileLockRetryLimit", 5).intValue(); + private static final int FILE_OPERATION_SLEEP_DELAY_MS = Integer.getInteger("com.sun.appserv.winFileLockRetryDelay", 1000).intValue(); + + + private FileUtils() { + // hidden } + /** * Result: existing writable directory given in parameter OR {@link IllegalStateException}. * @@ -110,12 +100,14 @@ public static void ensureWritableDir(File dir) { throw new IllegalStateException("The configured directory does not exist and could not be created: " + dir); } + /** * Wrapper for File.mkdirs * This version will return true if the directory exists when the method returns. * Unlike File.mkdirs which returns false if the directory already exists. + * * @param f The file pointing to the directory to be created - * @return + * @return true if the directory exists or was created by this method. */ public static boolean mkdirsMaybe(File f) { return f != null && (f.isDirectory() || f.mkdirs()); @@ -125,87 +117,72 @@ public static boolean mkdirsMaybe(File f) { * Wrapper for File.delete * This version will return true if the file does not exist when the method returns. * Unlike File.delete which returns false if the file does not exist. + * * @param f The file to be deleted - * @return + * @return true if the directory does not exist or was deleted by this method. */ public static boolean deleteFileMaybe(File f) { return f != null && (!f.exists() || f.delete()); } - /* - * Wrapper for File.listFiles - * Guaranteed to return an array in all cases. - * File.listFiles() returns either null or an empty array. This is annoying and results in harder - * than neccessry to read code -- i.e. there are 3 results possible: - * an array with files in it - * an empty array - * a null - */ + + /** + * Wrapper for File.listFiles + * Guaranteed to return an array in all cases. + * File.listFiles() returns either null or an empty array. + * This is annoying and results in harder than neccessry to read code -- i.e. there are 3 + * results possible: + *
    + *
  • an array with files in it + *
  • an empty array + *
  • a null + *
+ */ public static File[] listFiles(File f) { try { File[] files = f.listFiles(); - - if(files != null) { + if (files != null) { return files; } - } - catch(Exception e) { + } catch (Exception e) { // fall through } - return new File[0]; } + public static File[] listFiles(File f, FileFilter ff) { try { File[] files = f.listFiles(ff); - - if(files != null) { + if (files != null) { return files; } - } - catch(Exception e) { + } catch (Exception e) { // fall through } - return new File[0]; } public static File[] listFiles(File f, FilenameFilter fnf) { try { File[] files = f.listFiles(fnf); - - if(files != null) { + if (files != null) { return files; } - } - catch(Exception e) { + } catch (Exception e) { // fall through } - return new File[0]; } - /////////////////////////////////////////////////////////////////////////// public static boolean safeIsDirectory(File f) { - if (f == null || !f.exists() || !f.isDirectory()) { - return false; - } - - return true; + return f != null && f.exists() && f.isDirectory(); } - /////////////////////////////////////////////////////////////////////////// - - public static boolean safeIsRealDirectory(String s) { - return safeIsRealDirectory(new File(s)); - } - - /////////////////////////////////////////////////////////////////////////// public static boolean safeIsRealDirectory(File f) { - if (safeIsDirectory(f) == false) { + if (!safeIsDirectory(f)) { return false; } @@ -229,83 +206,56 @@ public static boolean safeIsRealDirectory(File f) { return false; } - /////////////////////////////////////////////////////////////////////////// - - public static boolean safeIsDirectory(String s) { - return safeIsDirectory(new File(s)); - } - - /////////////////////////////////////////////////////////////////////////// public static String safeGetCanonicalPath(File f) { if (f == null) { return null; } - try { return f.getCanonicalPath(); - } - catch (IOException e) { + } catch (IOException e) { return f.getAbsolutePath(); } } - /////////////////////////////////////////////////////////////////////////// public static File safeGetCanonicalFile(File f) { if (f == null) { return null; } - try { return f.getCanonicalFile(); - } - catch (IOException e) { + } catch (IOException e) { return f.getAbsoluteFile(); } } - /////////////////////////////////////////////////////////////////////////// - - public static boolean hasExtension(String filename, String ext) { - if (filename == null || filename.length() <= 0) { - return false; - } - - return filename.endsWith(ext); - } - - /////////////////////////////////////////////////////////////////////////// + /** + * @param f + * @param ext + * @return true if the file exists and it's name ends with ext + */ public static boolean hasExtension(File f, String ext) { if (f == null || !f.exists()) { return false; } - return f.getName().endsWith(ext); } - /////////////////////////////////////////////////////////////////////////// - - public static boolean hasExtensionIgnoreCase(String filename, String ext) { - if (filename == null || filename.length() <= 0) { - return false; - } - - return filename.toLowerCase(Locale.ENGLISH).endsWith(ext.toLowerCase(Locale.ENGLISH)); - } - - /////////////////////////////////////////////////////////////////////////// + /** + * @param f + * @param ext + * @return true if the file exists and it's name ends with ext (ignoring case) + */ public static boolean hasExtensionIgnoreCase(File f, String ext) { if (f == null || !f.exists()) { return false; } - return f.getName().toLowerCase(Locale.ENGLISH).endsWith(ext.toLowerCase(Locale.ENGLISH)); } - /////////////////////////////////////////////////////////////////////////// public static boolean isLegalFilename(String filename) { if (!isValidString(filename)) { @@ -321,7 +271,6 @@ public static boolean isLegalFilename(String filename) { return true; } - /////////////////////////////////////////////////////////////////////////// public static boolean isFriendlyFilename(String filename) { if (!isValidString(filename)) { @@ -335,7 +284,6 @@ public static boolean isFriendlyFilename(String filename) { return isLegalFilename(filename); } - /////////////////////////////////////////////////////////////////////////// public static String makeLegalFilename(String filename) { if (isLegalFilename(filename)) { @@ -353,16 +301,12 @@ public static String makeLegalFilename(String filename) { return filename; } - /////////////////////////////////////////////////////////////////////////// - public static String makeLegalNoBlankFileName(String filename) - { - return makeLegalFilename(filename).replace( - BLANK, REPLACEMENT_CHAR); + public static String makeLegalNoBlankFileName(String filename) { + return makeLegalFilename(filename).replace(BLANK, REPLACEMENT_CHAR); } - /////////////////////////////////////////////////////////////////////////// public static String makeFriendlyFilename(String filename) { if (isFriendlyFilename(filename)) { return filename; @@ -373,19 +317,6 @@ public static String makeFriendlyFilename(String filename) { return ret; } - /////////////////////////////////////////////////////////////////////////// - - public static String makeFriendlyFilenameNoExtension(String filename) { - int index = filename.lastIndexOf('.'); - - if (index > 0) { - filename = filename.substring(0, index); - } - - return (makeFriendlyFilename(filename)); - } - - /////////////////////////////////////////////////////////////////////////// public static String makeFriendlyFilenameExtension(String filename) { if (filename == null) { @@ -393,8 +324,7 @@ public static String makeFriendlyFilenameExtension(String filename) { } filename = makeLegalNoBlankFileName(filename); - - String extension = ""; + final String extension; if (filename.endsWith(".ear")) { filename = filename.substring(0, filename.indexOf(".ear")); extension = "_ear"; @@ -407,18 +337,20 @@ public static String makeFriendlyFilenameExtension(String filename) { } else if (filename.endsWith(".rar")) { filename = filename.substring(0, filename.indexOf(".rar")); extension = "_rar"; + } else { + extension = ""; } return filename + extension; } + public static String revertFriendlyFilenameExtension(String filename) { - if (filename == null || - !(filename.endsWith("_ear") || filename.endsWith("_war") || - filename.endsWith("_jar") || filename.endsWith("_rar"))) { + if (filename == null || (!filename.endsWith("_ear") && !filename.endsWith("_war") && !filename.endsWith("_jar") + && !filename.endsWith("_rar"))) { return filename; } - String extension = ""; + final String extension; if (filename.endsWith("_ear")) { filename = filename.substring(0, filename.indexOf("_ear")); extension = ".ear"; @@ -431,10 +363,13 @@ public static String revertFriendlyFilenameExtension(String filename) { } else if (filename.endsWith("_rar")) { filename = filename.substring(0, filename.indexOf("_rar")); extension = ".rar"; + } else { + extension = ""; } return filename + extension; } + public static String revertFriendlyFilename(String filename) { //first, revert the file extension @@ -444,39 +379,22 @@ public static String revertFriendlyFilename(String filename) { return name.replaceAll("__", "/"); } - ///////////////////////////////////////////////////////// public static void liquidate(File parent) { whack(parent); } - /////////////////////////////////////////////////////////////////////////// - - public static boolean isJar(String filename) - { - return hasExtension(filename, ".jar"); - } - - /////////////////////////////////////////////////////////////////////////// - - public static boolean isZip(String filename) - { - return hasExtensionIgnoreCase(filename, ".zip"); - } - - /////////////////////////////////////////////////////////////////////////// - public static boolean isJar(File f) - { + public static boolean isJar(File f) { return hasExtension(f, ".jar"); } - /////////////////////////////////////////////////////////////////////////// - public static boolean isZip(File f) - { + + public static boolean isZip(File f) { return hasExtensionIgnoreCase(f, ".zip"); } + /** * Deletes a directory and its contents. *

@@ -505,10 +423,8 @@ public static boolean whack(File parent) { */ public static boolean whack(File parent, Collection undeletedFiles) { try { - /* - *Resolve any links up-stream from this parent directory and - *then whack the resulting resolved directory. - */ + // Resolve any links up-stream from this parent directory and + // then whack the resulting resolved directory. return whackResolvedDirectory(parent.getCanonicalFile(), undeletedFiles); } catch (IOException ioe) { LOG.log(Level.ERROR, "Could not recursively delete the directory " + parent, ioe); @@ -530,10 +446,7 @@ public static boolean whack(File parent, Collection undeletedFiles) { * @return success or failure of deleting the directory */ private static boolean whackResolvedDirectory(File parent, Collection undeletedFiles) { - /* - *Do not recursively delete the contents if the current parent - *is a symbolic link. - */ + // Do not recursively delete the contents if the current parent is a symbolic link. if (safeIsRealDirectory(parent)) { File[] kids = listFiles(parent); @@ -546,10 +459,7 @@ private static boolean whackResolvedDirectory(File parent, Collection unde } } - - /* - *Delete the directory or symbolic link. - */ + // Delete the directory or symbolic link. return deleteFile(parent); } @@ -558,9 +468,11 @@ private static boolean whackResolvedDirectory(File parent, Collection unde * E.g. when Windows is using a jar in the current JVM -- you can not delete the jar until * the JVM dies. * @param f file to delete + * @deprecated Usually points to an IO leak */ + @Deprecated public static void deleteFileNowOrLater(File f) { - if(!deleteFile(f)) { + if (!deleteFile(f)) { f.deleteOnExit(); } } @@ -594,48 +506,34 @@ public static boolean deleteFile(File f) { * @return boolean indicating success or failure of the deletion atttempt; returns true if file is absent */ private static boolean internalDeleteFile(File f, boolean doWaitLoop) { - /* - *The operation succeeds immediately if the file is deleted - *successfully. On systems that support symbolic links, the file - *will be reported as non-existent if the file is a sym link to a - *non-existent directory. In that case invoke delete to remove - *the link before checking for existence, since File.exists on - *a symlink checks for the existence of the linked-to directory or - *file rather than of the link itself. - */ - if (!doWaitLoop) { - if (f.delete()) { - return true; - } - } - else { + // The operation succeeds immediately if the file is deleted successfully. + // On systems that support symbolic links, the file will be reported as non-existent if + // the file is a sym link to a non-existent directory. + // In that case invoke delete to remove the link before checking for existence, since + // File.exists on a symlink checks for the existence of the linked-to directory or + // file rather than of the link itself. + if (doWaitLoop) { DeleteFileWork work = new DeleteFileWork(f); - doWithRetry(work); - if (work.workComplete()) { return true; } + } else { + if (f.delete()) { + return true; + } } - String filePath = f.getAbsolutePath(); - - /* - *The deletion failed. This could be simply because the file - *does not exist. In that case, log an appropriate message and - *return. - */ - if (!f.exists()) { - LOG.log(TRACE, "Attempt to delete {0} failed; the file is reported as non-existent", f); - return true; - } else { - /* - *The delete failed and the file exists. Log a message if that - *level is enabled and return false to indicate the failure. - */ + // The deletion failed. This could be simply because the file does not exist. + // In that case, log an appropriate message and return. + if (f.exists()) { + // The delete failed and the file exists. + // Log a message if that level is enabled and return false to indicate the failure. LOG.log(WARNING, "Error attempting to delete {0}", f); return false; } + LOG.log(Level.TRACE, "Attempt to delete {0} failed; the file is reported as non-existent", f); + return true; } /** @@ -653,31 +551,10 @@ public static FileOutputStream openFileOutputStream(File out) throws IOException } if (work.workComplete()) { return work.getStream(); - } else { - IOException ioe = new IOException(); - ioe.initCause(work.getLastError()); - throw ioe; - } - } - - /** - * Return a set of all the files (File objects) under the directory specified, with - * relative pathnames filtered with the filename filter (can be null for all files). - */ - public static Set getAllFilesUnder(File directory, FilenameFilter filenameFilter) throws IOException { - if (!directory.exists() || !directory.isDirectory()) { - throw new IOException("Problem with: " + directory + ". You must supply a directory that exists"); } - return getAllFilesUnder(directory, filenameFilter, true); + throw new IOException("Failed opening file for output: " + out, work.getLastError()); } - public static Set getAllFilesUnder(File directory, FilenameFilter filenameFilter, boolean relativize) throws IOException { - Set allFiles = new TreeSet<>(); - File relativizingDir = relativize ? directory : null; - recursiveGetFilesUnder( relativizingDir, directory, filenameFilter, - allFiles, false ); - return allFiles; - } public static Set getAllFilesAndDirectoriesUnder(File directory) throws IOException { if (!directory.exists() || !directory.isDirectory()) { @@ -688,28 +565,27 @@ public static Set getAllFilesAndDirectoriesUnder(File directory) throws IO return allFiles; } - // relativizingRoot can be null, in which case no relativizing is - // performed. + // relativizingRoot can be null, in which case no relativizing is performed. private static void recursiveGetFilesUnder(File relativizingRoot, File directory, FilenameFilter filenameFilter, Set set, boolean returnDirectories) { File[] files = listFiles(directory, filenameFilter); for (File file : files) { if (file.isDirectory()) { recursiveGetFilesUnder(relativizingRoot, file, filenameFilter, set, returnDirectories); if (returnDirectories) { - if( relativizingRoot != null ) { + if (relativizingRoot != null) { set.add(relativize(relativizingRoot, file)); } else { set.add(file); } } } else { - if( relativizingRoot != null ) { + if (relativizingRoot != null) { set.add(relativize(relativizingRoot, file)); } else { set.add(file); } } - } + } } /** @@ -717,18 +593,15 @@ private static void recursiveGetFilesUnder(File relativizingRoot, File directory * under that directory, return the portion of the child * that is relative to the parent. */ - public static File relativize(File parent, File child) { - String baseDir = parent.getAbsolutePath(); + private static File relativize(File parent, File child) { + String baseDir = parent.getAbsolutePath(); String baseDirAndChild = child.getAbsolutePath(); - - String relative = baseDirAndChild.substring(baseDir.length(), - baseDirAndChild.length()); + String relative = baseDirAndChild.substring(baseDir.length(), baseDirAndChild.length()); // Strip off any extraneous file separator character. - if( relative.startsWith(File.separator) ) { + if (relative.startsWith(File.separator)) { relative = relative.substring(1); } - return new File(relative); } @@ -739,19 +612,17 @@ public static File relativize(File parent, File child) { * * @param work the RetriableWork implementation to be run * @return the number of retries performed; 0 indicates the work succeeded without having to retry + * @deprecated The situation usually means there's an IO leak. */ + @Deprecated private static int doWithRetry(RetriableWork work) { int retries = 0; - /* - *Try the work the first time. Ideally this will work. - */ + // Try the work the first time. Ideally this will work. work.run(); - /* - *If the work failed and this is Windows - on which running gc may - *unlock the locked file - then begin the retries. - */ + // If the work failed and this is Windows - on which running gc may + // unlock the locked file - then begin the retries. if (!work.workComplete() && OS.isWindows()) { while (!work.workComplete() && retries++ < FILE_OPERATION_MAX_RETRIES) { try { @@ -766,127 +637,11 @@ private static int doWithRetry(RetriableWork work) { return retries; } - /** - * Creates a String listing the absolute paths of files, separated by - * the platform's line separator. - * - * @param files the Collection of File objects to be listed - * @return String containing the absolute paths of the files with the line separator between them - */ - public static String formatFileCollection(Collection files) { - StringBuilder sb = new StringBuilder(); - String lineSep = System.getProperty("line.separator"); - String prefix = ""; - for (File f : files) { - sb.append(prefix).append(f.getAbsolutePath()); - prefix = lineSep; - } - return sb.toString(); - } - /////////////////////////////////////////////////////////////////////////// - - public static File getDirectory(File f) { - String filename = f.getAbsolutePath(); - return new File((new File(filename)).getParent()); - } - - /////////////////////////////////////////////////////////////////////////// - - public static File createTempFile(File directory) { - File f = null; - - try { - f = File.createTempFile(TMPFILENAME, "jar", directory); - } - catch (IOException ioe) { - LOG.log(Level.ERROR, CULoggerInfo.exceptionIO, ioe); - } - - f.deleteOnExit(); // just in case - return f; - } - - /** - * Returns an array of abstract pathnames that matches with the given - * file extension. If the given abstract pathname does not denote a - * directory, then this method returns null. If there is no matching - * file under the given directory and its sub directories, - * it returns null; - * - * @param dirName dir name under which search will begin - * @param ext file extension to look for - * @return an array of abstract pathnames that matches with the extension - */ - public static File[] listAllFiles(File dirName, String ext) { - File[] target = null; - List list = searchDir(dirName, ext); - - if ((list != null) && (list.size() > 0)) { - target = new File[list.size()]; - target = list.toArray(target); - } - - return target; - } - - /** - * Returns a list of abstract pathnames that matches with the given - * file extension. If the given abstract pathname does not denote a - * directory, then this method returns null. If there is no matching - * file under the given directory and its sub directories, it returns - * an empty list. - * - * @param dirName dir name under which search will begin - * @param ext file extension to look for - * @return a list of abstract pathnames of type java.io.File - * that matches with the given extension - */ - public static List searchDir(File dirName, String ext) { - List targetList = null; - - if (dirName.isDirectory()) { - targetList = new ArrayList<>(); - - File[] list = listFiles(dirName); - - for (File element : list) { - if (element.isDirectory()) { - targetList.addAll(searchDir(element, ext)); - } else { - String name = element.toString(); - if (hasExtension(name, ext)) { - targetList.add(element); - } - } - } - } - - return targetList; - } - - /** - * Copies a file. - * - * @param from Name of file to copy - * @param to Name of new file - * @throws IOException if an error while copying the content - */ - public static void copy(String from, String to) throws IOException { - //if(!StringUtils.ok(from) || !StringUtils.ok(to)) - if (from == null || to == null) { - throw new IllegalArgumentException("null or empty filename argument"); - } - - File fin = new File(from); - File fout = new File(to); - - copy(fin, fout); - } /** * Copies a file. * - * @param fin File to copy + * @param fin File to copy * @param fout New file * @throws IOException if an error while copying the content */ @@ -895,18 +650,16 @@ public static void copy(File fin, File fout) throws IOException { copyTree(fin, fout); return; } - if (!fin.exists()) { throw new IllegalArgumentException("File source doesn't exist"); } - - if(!mkdirsMaybe(fout.getParentFile())) { - throw new RuntimeException("Can't create parent dir of output file: " + fout); - } - - copyFile(fin, fout); + if (!mkdirsMaybe(fout.getParentFile())) { + throw new RuntimeException("Can't create parent dir of output file: " + fout); + } + Files.copy(fin.toPath(), fout.toPath()); } + /** * Copies the entire tree to a new location. * @@ -914,13 +667,12 @@ public static void copy(File fin, File fout) throws IOException { * @param dout File pointing at root of new tree * @throws IOException if an error while copying the content */ - public static void copyTree(File din, File dout) - throws IOException { + public static void copyTree(File din, File dout) throws IOException { if (!safeIsDirectory(din)) { throw new IllegalArgumentException("Source isn't a directory"); } - if(!mkdirsMaybe(dout)) { + if (!mkdirsMaybe(dout)) { throw new IllegalArgumentException("Can't create destination directory"); } @@ -930,7 +682,6 @@ public static void copyTree(File din, File dout) for (String file : files) { File fin = new File(din, file); File fout = new File(dout, file); - copy(fin, fout); } } @@ -949,9 +700,10 @@ public static String makeForwardSlashes(String inputStr) { if (inputStr == null) { throw new IllegalArgumentException("null String FileUtils.makeForwardSlashes"); } - return (inputStr.replace('\\', '/')); + return inputStr.replace('\\', '/'); } + /** * Given a string (typically a path), quote the string such that spaces * are protected from interpretation by a Unix or Windows command shell. @@ -967,9 +719,9 @@ public static String quoteString(String s) { } if (!s.contains("\'")) { - return("\'" + s + "\'"); - } else if(!s.contains("\"")) { - return("\"" + s + "\""); + return ("\'" + s + "\'"); + } else if (!s.contains("\"")) { + return ("\"" + s + "\""); } else { // Contains a single quote and a double quote. Use backslash // On Unix. Double quotes on Windows. This method does not claim @@ -982,337 +734,182 @@ public static String quoteString(String s) { } } - /////////////////////////////////////////////////////////////////////////// - public static String getIllegalFilenameCharacters() { - return ILLEGAL_FILENAME_STRING; + static boolean isValidString(String s) { + return s != null && !s.isEmpty(); } - /////////////////////////////////////////////////////////////////////////// - static boolean isValidString(String s) { - return ((s != null) && (s.length() != 0)); + /** + * @param in It will be closed after processing, doesn't need to be buffered as this method uses + * own 8K buffer. + * @param out Target output file. + * @param bytes Maximal count of bytes to be transferred + * @throws IOException + */ + public static void copy(InputStream in, File out, long bytes) throws IOException { + try (ReadableByteChannel inputChannel = Channels.newChannel(new BufferedInputStream(in)); + FileOutputStream output = new FileOutputStream(out)) { + output.getChannel().transferFrom(inputChannel, 0, bytes); + } } /** - * This method is used to copy a given file to another file - * using the buffer sixe specified + * Copies stream with internal 8K buffer. * - * @param fin the source file - * @param fout the destination file + * @param in It is NOT closed after processing, caller is responsible for that. + * @param os It is NOT closed after processing, caller is responsible for that. + * + * @throws IOException */ - public static void copyFile(File fin, File fout) throws IOException { - - InputStream inStream = new BufferedInputStream(new FileInputStream(fin)); - FileOutputStream fos = FileUtils.openFileOutputStream(fout); - copy(inStream, fos, fin.length()); + public static void copy(InputStream in, OutputStream os) throws IOException { + final ReadableByteChannel inputChannel = Channels.newChannel(in); + final WritableByteChannel outputChannel = getChannel(os); + if (outputChannel instanceof FileChannel) { + // Can be optimized by the operating system + FileChannel foch = (FileChannel) outputChannel; + foch.transferFrom(inputChannel, 0, Long.MAX_VALUE); + return; + } + ByteBuffer byteBuffer = ByteBuffer.allocate(8192); + int read; + do { + read = inputChannel.read(byteBuffer); + if (read > 0) { + byteBuffer.flip(); + outputChannel.write(byteBuffer); + byteBuffer.clear(); + } + } while (read != -1); } - public static void copy(InputStream in, FileOutputStream out, long size) throws IOException { - - try { - copyWithoutClose(in, out, size); - } finally { - if (in != null) { - in.close(); - } - if (out != null) { - out.close(); - } + private static WritableByteChannel getChannel(final OutputStream stream) { + if (stream instanceof FileOutputStream) { + return ((FileOutputStream) stream).getChannel(); } + if (stream instanceof WritableArchiveEntry) { + return ((WritableArchiveEntry) stream).getChannel(); + } + return Channels.newChannel(stream); } - public static void copyWithoutClose(InputStream in, FileOutputStream out, long size) throws IOException { - - ReadableByteChannel inChannel = Channels.newChannel(in); - FileChannel outChannel = out.getChannel(); - outChannel.transferFrom(inChannel, 0, size); - } - - public static void copy(InputStream in, OutputStream os, long size) throws IOException { - if (os instanceof FileOutputStream) { - copy(in, (FileOutputStream) os, size); + /** + * Rename, running gc on Windows if needed to try to force open streams to close. + * + * @param fromFile to be renamed + * @param toFile name for the renamed file + * @return boolean result of the rename attempt + */ + public static boolean renameFile(File fromFile, File toFile) { + RenameFileWork renameWork = new RenameFileWork(fromFile, toFile); + int retries = doWithRetry(renameWork); + boolean result = renameWork.workComplete(); + if (result) { + LOG.log(DEBUG, "Attempt to rename {0} to {1} succeeded after {2} retries", fromFile, toFile, retries); } else { - ReadableByteChannel inChannel = Channels.newChannel(in); - WritableByteChannel outChannel = Channels.newChannel(os); - if (size==0) { - - ByteBuffer byteBuffer = ByteBuffer.allocate(10240); - int read; - do { - read = inChannel.read(byteBuffer); - if (read>0) { - byteBuffer.limit(byteBuffer.position()); - byteBuffer.rewind(); - outChannel.write(byteBuffer); - byteBuffer.clear(); - } - } while (read!=-1); - } else { - ByteBuffer byteBuffer; - try{ - byteBuffer = ByteBuffer.allocate(Long.valueOf(size).intValue()); - }catch(Throwable err){ - throw new IOException(messages.get("allocate.more.than.java.heap.space", err)); - } - inChannel.read(byteBuffer); - byteBuffer.rewind(); - outChannel.write(byteBuffer); - } + LOG.log(WARNING, "Attempt to rename {0} to {1} failed after {2} retries", fromFile, toFile, retries); } + return result; } - /** - *Rename, running gc on Windows if needed to try to force open streams to close. - *@param fromFile to be renamed - *@param toFile name for the renamed file - *@return boolean result of the rename attempt - */ - public static boolean renameFile(File fromFile, File toFile) { - RenameFileWork renameWork = new RenameFileWork(fromFile, toFile); - int retries = doWithRetry(renameWork); - boolean result = renameWork.workComplete(); - if (result) { - LOG.log(DEBUG, "Attempt to rename {0} to {1} succeeded after {2} retries", fromFile, toFile, retries); - } else { - LOG.log(WARNING, "Attempt to rename {0} to {1} failed after {2} retries", fromFile, toFile, retries); - } - return result; - } - - /** Appends the given line at the end of given text file. If the given - * file does not exist, an attempt is made to create it. - * Note that this method can handle only text files. - * @param fileName name of the text file that needs to be appended to - * @param line the line to append to - * @throws RuntimeException in case of any error - that makes it callable - * from a code not within try-catch. Note that NPE will be thrown if either - * argument is null. - * Note that this method is not tested with String containing characters - * with 2 bytes. - */ - public static void appendText(String fileName, String line) throws - RuntimeException { - RandomAccessFile file = null; - try { - final String MODE = "rw"; - file = new RandomAccessFile(fileName, MODE); - file.seek(file.getFilePointer() + file.length()); - file.writeBytes(line); - } - catch(Exception e) { - throw new RuntimeException("FileUtils.appendText()", e); - } - finally { - try { - if (file != null) { - file.close(); - } - } - catch(Exception e){} - } - } - public static void appendText(String fileName, StringBuffer buffer) - throws IOException, FileNotFoundException - { - appendText(fileName, buffer.toString()); - } - /////////////////////////////////////////////////////////////////////////// - /** A utility routine to read a text file efficiently and return + /** + * A utility routine to read a text file efficiently and return * the contents as a String. Sometimes while reading log files of spawned * processes this kind of facility is handy. Instead of opening files, coding * FileReaders etc. this method could be employed. It is expected that the * file to be read is small . - * @param fileName String representing absolute path of the file + * + * @param file Absolute path of the file * @return String representing the contents of the file, empty String for an empty file * @throws java.io.IOException if there is an i/o error. * @throws java.io.FileNotFoundException if the file could not be found */ - public static String readSmallFile(final String fileName) - throws IOException, FileNotFoundException { - return (readSmallFile(new File(fileName)) ); - } - - public static String readSmallFile(final File file) - throws IOException { - final BufferedReader bf = new BufferedReader(new FileReader(file)); - final StringBuilder sb = new StringBuilder(); //preferred over StringBuffer, no need to synchronize - String line = null; - try { - while ( (line = bf.readLine()) != null ) { + public static String readSmallFile(final File file) throws IOException { + final StringBuilder sb = new StringBuilder(); + try (BufferedReader bf = new BufferedReader(new FileReader(file))) { + String line; + while ((line = bf.readLine()) != null) { sb.append(line); - sb.append(System.getProperty("line.separator")); + sb.append(System.lineSeparator()); } } - finally { - try { - bf.close(); - } - catch (Exception e) {} - } - return ( sb.toString() ); + return sb.toString(); } + /** - * If the path dir/file does not exist, look for it in the classpath. If found - * in classpath, create dir/file. + * If the path dir/file does not exist, look for it in the classpath. + * If found in classpath, create dir/file. * * @param file - path to look for * @param dir - directory where the path file should exist * @return the File representing dir/file. If that does not exist, return null. * @throws IOException */ - public static File getManagedFile(String file, File dir) throws IOException { File f = new File(dir, file); if (f.exists()) { return f; } - InputStream is = null, bis = null; - OutputStream os = null; - try { - is = Thread.currentThread().getContextClassLoader().getResourceAsStream(file); + try (InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream(file)) { if (is == null) { return null; } - bis = new BufferedInputStream(is); - - if(!mkdirsMaybe(f.getParentFile())) { - throw new RuntimeException("Can't create parent dir of output file: " + f); - } - - os = new BufferedOutputStream(FileUtils.openFileOutputStream(f)); - byte buf[] = new byte[10240]; - int len = 0; - while ((len =bis.read(buf)) > 0) { - os.write(buf, 0, len); + try (InputStream bis = new BufferedInputStream(is)) { + if (!mkdirsMaybe(f.getParentFile())) { + throw new IOException("Can't create parent dir of output file: " + f); + } + try (OutputStream os = new BufferedOutputStream(FileUtils.openFileOutputStream(f))) { + byte buf[] = new byte[10240]; + int len = 0; + while ((len = bis.read(buf)) > 0) { + os.write(buf, 0, len); + } + } } return f; - } finally { - if (os != null) { - try { - os.close(); - } catch (IOException ex) {} - } - - if (bis != null) { - try { - bis.close(); - } catch (IOException ex) {} - } - - if (is != null) { - try { - is.close(); - } catch (IOException ex) {} - } } } + /** - * Write the String to a file. Then make the file readable and writable. + * Write the String to a file. Then make the file readable and writable. * If the file already exists it will be truncated and the contents replaced * with the String argument. + * * @param s The String to write to the file * @param f The file to write the String to * @throws IOException if any errors */ public static void writeStringToFile(String s, File f) throws IOException { - Writer writer = null; - - try { - writer = new PrintWriter(f); + try (Writer writer = new PrintWriter(f)) { writer.write(s); + } finally { + f.setReadable(true); + f.setWritable(true); } - finally { - if(writer != null) { - try { - writer.close(); - } - catch(Exception e) { - //ignore - } - f.setReadable(true); - f.setWritable(true); - } - } - } -/** - * Find files matching the regular expression in the given directory - * @param dir the directory to search - * @param regexp the regular expression pattern - * @return either an array of matching File objects or an empty array. Guaranteed - * to never return null - */ - public static File[] findFilesInDir(File dir, final String regexp) { - try { - File[] matches = dir.listFiles(new FilenameFilter() { - @Override - public boolean accept(File dir, String name) { - return name.matches(regexp); - } - }); - if (matches != null) { - return matches; - } - } - catch (Exception e) { - // fall through - } - return new File[0]; } - /** - * Read in the given resourceName as a resource, and convert to a String - * - * @param resourceName - * @return the contents of the resource as a String or null if absent - */ - public static String resourceToString(String resourceName) { - byte[] bytes = resourceToBytes(resourceName); - - return bytes == null ? null : new String(bytes); - } /** - * Read in the given resourceName as a resource, and convert to a byte array + * Find files matching the regular expression in the given directory * - * @param resourceName - * @return the contents of the resource as a byte array or null if absent + * @param dir the directory to search + * @param regexp the regular expression pattern + * @return either an array of matching File objects or an empty array. Guaranteed + * to never return null */ - public static byte[] resourceToBytes(String resourceName) { - ClassLoader cl = Thread.currentThread().getContextClassLoader(); - InputStream is = cl.getResourceAsStream(resourceName); - - if (is == null) { - return null; - } - - try { - is = new BufferedInputStream(is); - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - byte[] buffer = new byte[1024]; - int n; - - while ((n = is.read(buffer)) != -1) { - baos.write(buffer, 0, n); - } - is.close(); - return baos.toByteArray(); - } - catch (Exception e) { - try { - is.close(); - } - catch (Exception ex) { - // ignore... - } - return null; + public static File[] findFilesInDir(File dir, final String regexp) { + File[] matches = dir.listFiles((dir1, name) -> name.matches(regexp)); + if (matches == null) { + LOG.log(Level.WARNING, "Could not list files in {0}. Check permissions!", dir); + return new File[0]; } + return matches; } /** @@ -1337,13 +934,13 @@ private interface RetriableWork extends Runnable { } /** - *Retriable work for renaming a file. + * Retriable work for renaming a file. */ private static class RenameFileWork implements RetriableWork { private final File originalFile; private final File newFile; - private boolean renameResult = false; + private boolean renameResult; public RenameFileWork(File originalFile, File newFile) { this.originalFile = originalFile; @@ -1366,8 +963,8 @@ public void run() { */ private static class FileOutputStreamWork implements RetriableWork { - private FileOutputStream fos = null; - private Throwable lastError = null; + private FileOutputStream fos; + private Throwable lastError; private final File out; public FileOutputStreamWork(File out) { @@ -1401,10 +998,10 @@ public Throwable getLastError() { /** * Retriable work for deleting a file */ - private static class DeleteFileWork implements RetriableWork { + private static final class DeleteFileWork implements RetriableWork { private final File deleteMe; - private boolean complete = false; + private boolean complete; private DeleteFileWork(File deleteMe) { this.deleteMe = deleteMe; @@ -1415,7 +1012,6 @@ public void run() { if (complete) { return; } - if (deleteMe.delete()) { complete = true; } @@ -1425,21 +1021,5 @@ public void run() { public boolean workComplete() { return complete; } - - } - - /////////////////////////////////////////////////////////////////////////// - - private final static char[] ILLEGAL_FILENAME_CHARS = {'/', '\\', ':', '*', '?', '"', '<', '>', '|'}; - private final static String ILLEGAL_FILENAME_STRING = "\\/:*?\"<>|"; - private final static char REPLACEMENT_CHAR = '_'; - private final static char BLANK = ' '; - private final static char DOT = '.'; - private static String TMPFILENAME = "scratch"; - /* - *The following property names are private, unsupported, and unpublished. - */ - private static final int FILE_OPERATION_MAX_RETRIES = Integer.getInteger("com.sun.appserv.winFileLockRetryLimit", 5).intValue(); - private static final int FILE_OPERATION_SLEEP_DELAY_MS = Integer.getInteger("com.sun.appserv.winFileLockRetryDelay", 1000).intValue(); } diff --git a/nucleus/common/common-util/src/main/java/com/sun/enterprise/util/io/LocalStrings.properties b/nucleus/common/common-util/src/main/java/com/sun/enterprise/util/io/LocalStrings.properties index 32c39349c37..47de09275a6 100644 --- a/nucleus/common/common-util/src/main/java/com/sun/enterprise/util/io/LocalStrings.properties +++ b/nucleus/common/common-util/src/main/java/com/sun/enterprise/util/io/LocalStrings.properties @@ -15,7 +15,6 @@ # # i18n Strings for com.sun.enterprise.util.io -allocate.more.than.java.heap.space=Trying to allocate a buffer bigger than the current allocated Java heap space. ServerDirs.badDir=Directory doesn''t exist: {0} ## The parent directory of {server directory} doesn''t exist. ServerDirs.badParentDir=The parent directory of {0} doesn''t exist. diff --git a/nucleus/common/common-util/src/main/java/com/sun/enterprise/util/shared/ArchivistUtils.java b/nucleus/common/common-util/src/main/java/com/sun/enterprise/util/shared/ArchivistUtils.java deleted file mode 100644 index 5fce42e9873..00000000000 --- a/nucleus/common/common-util/src/main/java/com/sun/enterprise/util/shared/ArchivistUtils.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (c) 2006, 2018 Oracle and/or its affiliates. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0, which is available at - * http://www.eclipse.org/legal/epl-2.0. - * - * This Source Code may also be made available under the following Secondary - * Licenses when the conditions for such availability set forth in the - * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, - * version 2 with the GNU Classpath Exception, which is available at - * https://www.gnu.org/software/classpath/license.html. - * - * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 - */ - -package com.sun.enterprise.util.shared; - -import java.io.EOFException; -import java.io.InputStream; -import java.io.IOException; -import java.io.OutputStream; - -/** - * This class contains utility methods that handles the archives. - * - * @author Deployment Dev Team - * @version - */ -public class ArchivistUtils { - - /** - * Utility method that eads the input stream fully and writes the bytes to - * the current entry in the output stream. - */ - public static void copy(InputStream is, OutputStream os) throws IOException { - copyWithoutClose(is, os); - is.close(); - os.close(); - } - - /** - * Utility method that eads the input stream fully and writes the bytes to - * the current entry in the output stream. - */ - public static void copyWithoutClose(InputStream is, OutputStream os) throws IOException { - byte[] buf = new byte[4096]; - int len = 0; - while (len != -1) { - try { - len = is.read(buf, 0, buf.length); - } catch (EOFException eof){ - break; - } - - if(len != -1) { - os.write(buf, 0, len); - } - } - os.flush(); - } -} diff --git a/nucleus/common/common-util/src/main/java/com/sun/enterprise/util/zip/ZipFile.java b/nucleus/common/common-util/src/main/java/com/sun/enterprise/util/zip/ZipFile.java index e363735d395..abac13577f6 100644 --- a/nucleus/common/common-util/src/main/java/com/sun/enterprise/util/zip/ZipFile.java +++ b/nucleus/common/common-util/src/main/java/com/sun/enterprise/util/zip/ZipFile.java @@ -1,6 +1,6 @@ /* + * Copyright (c) 2021, 2022 Contributors to the Eclipse Foundation * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2021 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 @@ -22,12 +22,21 @@ import com.sun.enterprise.util.CULoggerInfo; import com.sun.enterprise.util.io.FileUtils; -import java.io.*; -import java.util.*; + +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; import java.util.jar.JarFile; import java.util.logging.Level; import java.util.logging.Logger; -import java.util.zip.*; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; /////////////////////////////////////////////////////////////////////////////// public class ZipFile { @@ -76,7 +85,7 @@ public ZipFile(InputStream inStream, File anExplodeDir) throws ZipFileException */ ////////////////////////////////////////////////////////////////////////////////////////////////////////////// public ArrayList explode() throws ZipFileException { - files = new ArrayList(); + files = new ArrayList<>(); ZipInputStream zin = null; BufferedOutputStream bos = null; @@ -185,15 +194,12 @@ public static void extractJar(String jarEntryName, JarFile earFile, ZipEntry jarEntry = earFile.getEntry(jarEntryName); if (jarEntry == null) { - throw new ZipFileException(jarEntryName - + " not found in " + earFile.getName()); + throw new ZipFileException(jarEntryName + " not found in " + earFile.getName()); } - InputStream is = earFile.getInputStream(jarEntry); - FileOutputStream fos = new FileOutputStream(jarFile); - // the FileUtils.copy will buffer the streams, - // so we won't buffer them here. - FileUtils.copy(is, fos, jarEntry.getSize()); + try (InputStream is = earFile.getInputStream(jarEntry)) { + FileUtils.copy(is, jarFile, jarEntry.getSize()); + } } catch (IOException e) { throw new ZipFileException(e); } @@ -333,7 +339,7 @@ private static void insist(boolean b, String mesg) throws ZipFileException { private static final int BUFFER_SIZE = 0x10000; //64k private File explodeDir = null; private ArrayList files = null; - private byte[] buffer = new byte[BUFFER_SIZE]; + private final byte[] buffer = new byte[BUFFER_SIZE]; private ZipInputStream zipStream = null; private static final Logger _utillogger = CULoggerInfo.getLogger(); private File zipFile = null; diff --git a/nucleus/common/common-util/src/main/java/org/glassfish/admin/payload/PayloadFilesManager.java b/nucleus/common/common-util/src/main/java/org/glassfish/admin/payload/PayloadFilesManager.java index 6e816b7e269..08804ce8d80 100644 --- a/nucleus/common/common-util/src/main/java/org/glassfish/admin/payload/PayloadFilesManager.java +++ b/nucleus/common/common-util/src/main/java/org/glassfish/admin/payload/PayloadFilesManager.java @@ -1,4 +1,5 @@ /* + * Copyright (c) 2022 Contributors to the Eclipse Foundation * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the @@ -18,6 +19,7 @@ import com.sun.enterprise.util.LocalStringManagerImpl; import com.sun.enterprise.util.io.FileUtils; + import java.io.BufferedOutputStream; import java.io.File; import java.io.FileNotFoundException; @@ -38,6 +40,7 @@ import java.util.Properties; import java.util.logging.Level; import java.util.logging.Logger; + import org.glassfish.api.ActionReport; import org.glassfish.api.admin.Payload; import org.glassfish.api.admin.Payload.Part; @@ -76,7 +79,7 @@ public abstract class PayloadFilesManager { private final ActionReport report; private final ActionReportHandler reportHandler; - protected final Map dirTimestamps = new HashMap(); + protected final Map dirTimestamps = new HashMap<>(); private PayloadFilesManager( final File targetDir, @@ -431,22 +434,18 @@ private File replaceFile(final Payload.Part part) throws IOException { } private void consumePartBody(final Part part) throws FileNotFoundException, IOException { - InputStream is = null; - try { - is = part.getInputStream(); + try (InputStream is = part.getInputStream()) { byte[] buffer = new byte[1024 * 64]; while (is.read(buffer) != -1) { } - } finally { - if (is != null) { - is.close(); - } } } private void processReport(final Payload.Part part) throws Exception { if (reportHandler != null) { - reportHandler.handleReport(part.getInputStream()); + try (InputStream inputStream = part.getInputStream()) { + reportHandler.handleReport(inputStream); + } } else { consumePartBody(part); } @@ -581,7 +580,7 @@ public Map processPartsExtended( return Collections.EMPTY_MAP; } - final Map result = new LinkedHashMap(); + final Map result = new LinkedHashMap<>(); boolean isReportProcessed = false; Part possibleUnrecognizedReportPart = null; @@ -620,11 +619,11 @@ public Map processPartsExtended( public List processParts( final Payload.Inbound inboundPayload) throws Exception { - return new ArrayList(processPartsExtended(inboundPayload).keySet()); + return new ArrayList<>(processPartsExtended(inboundPayload).keySet()); } - public static interface ActionReportHandler { - public void handleReport(final InputStream reportStream) throws Exception; + public interface ActionReportHandler { + void handleReport(final InputStream reportStream) throws Exception; } protected abstract void postProcessParts(); @@ -766,7 +765,7 @@ protected File processPart( * Creates a new instance of the enum * @param type */ - private DataRequestType(final String type) { + DataRequestType(final String type) { dataRequestType = type; } diff --git a/nucleus/common/common-util/src/test/java/com/sun/enterprise/util/io/FileUtilsTest.java b/nucleus/common/common-util/src/test/java/com/sun/enterprise/util/io/FileUtilsTest.java index 2b0552b8b75..720c8dce5e8 100644 --- a/nucleus/common/common-util/src/test/java/com/sun/enterprise/util/io/FileUtilsTest.java +++ b/nucleus/common/common-util/src/test/java/com/sun/enterprise/util/io/FileUtilsTest.java @@ -1,6 +1,6 @@ /* + * Copyright (c) 2021, 2022 Contributors to the Eclipse Foundation * Copyright (c) 2011, 2018 Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2021 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 @@ -17,16 +17,11 @@ package com.sun.enterprise.util.io; -import com.sun.enterprise.universal.io.SmartFile; - import java.io.File; import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertTrue; /** @@ -61,70 +56,5 @@ public void testMkdirsMaybe() { if (!d2.delete()) { d2.deleteOnExit(); } - - } - - - @Test - public void testParent() { - File f = null; - assertNull(FileUtils.getParentFile(f)); - f = new File("/foo/././././."); - File wrongGrandParent = f.getParentFile().getParentFile(); - File correctParent = FileUtils.getParentFile(f); - File sanitizedChild = SmartFile.sanitize(f); - File sanitizedWrongGrandParent = SmartFile.sanitize(wrongGrandParent); - File shouldBeSameAsChild = new File(correctParent, "foo"); - - // check this out -- surprise!!!! - assertEquals(sanitizedWrongGrandParent, sanitizedChild); - assertEquals(shouldBeSameAsChild, sanitizedChild); - } - - - @Test - public void testResourceToString() { - String resname = "simplestring.txt"; - String contents = "Simple String Here!"; - String fetched = FileUtils.resourceToString(resname); - assertEquals(contents, fetched); - } - - - @Test - public void testEmptyButExistingResourceToString() { - String resname = "empty.txt"; - String fetched = FileUtils.resourceToString(resname); - assertNotNull(fetched); - assertTrue(fetched.length() == 0); - } - - - @Test - public void testNonExistingResourceToString() { - String resname = "doesnotexist.txt"; - String fetched = FileUtils.resourceToString(resname); - assertNull(fetched); - } - - - @Test - public void testNonExistingResourceToBytes() { - String resname = "doesnotexist.txt"; - byte[] fetched = FileUtils.resourceToBytes(resname); - // null -- not an empty array! - assertNull(fetched); - } - - - @Test - public void testResourceToBytes() { - String resname = "verysimplestring.txt"; - byte[] fetched = FileUtils.resourceToBytes(resname); - - assertEquals(fetched[0], 65); - assertEquals(fetched[1], 66); - assertEquals(fetched[2], 67); - assertEquals(fetched.length, 3); } } diff --git a/nucleus/common/common-util/src/test/resources/empty.txt b/nucleus/common/common-util/src/test/resources/empty.txt deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/nucleus/common/common-util/src/test/resources/simplestring.txt b/nucleus/common/common-util/src/test/resources/simplestring.txt deleted file mode 100644 index e88c2627b49..00000000000 --- a/nucleus/common/common-util/src/test/resources/simplestring.txt +++ /dev/null @@ -1 +0,0 @@ -Simple String Here! \ No newline at end of file diff --git a/nucleus/common/common-util/src/test/resources/v2domain.xml b/nucleus/common/common-util/src/test/resources/v2domain.xml deleted file mode 100644 index 444e5768a48..00000000000 --- a/nucleus/common/common-util/src/test/resources/v2domain.xml +++ /dev/null @@ -1,224 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -XX:MaxPermSize=192m - -client - -Djava.security.policy=${com.sun.aas.instanceRoot}/config/server.policy - -Djava.security.auth.login.config=${com.sun.aas.instanceRoot}/config/login.conf - -Dsun.rmi.dgc.server.gcInterval=3600000 - -Dsun.rmi.dgc.client.gcInterval=3600000 - -Xmx512m - -Djavax.net.ssl.keyStore=${com.sun.aas.instanceRoot}/config/keystore.jks - -Djavax.net.ssl.trustStore=${com.sun.aas.instanceRoot}/config/cacerts.jks - -Djava.ext.dirs=${com.sun.aas.javaRoot}/lib/ext${path.separator}${com.sun.aas.javaRoot}/jre/lib/ext${path.separator}${com.sun.aas.instanceRoot}/lib/ext${path.separator}${com.sun.aas.derbyRoot}/lib - -Djdbc.drivers=org.apache.derby.jdbc.ClientDriver - -Djavax.management.builder.initial=com.sun.enterprise.admin.server.core.jmx.AppServerMBeanServerBuilder - -Dcom.sun.enterprise.config.config_environment_factory_class=com.sun.enterprise.config.serverbeans.AppserverConfigEnvironmentFactory - -Dcom.sun.enterprise.taglibs=appserv-jstl.jar,jakarta.faces.jar - -Dcom.sun.enterprise.taglisteners=jakarta.faces.jar - -XX:NewRatio=2 - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/nucleus/common/common-util/src/test/resources/verysimplestring.txt b/nucleus/common/common-util/src/test/resources/verysimplestring.txt deleted file mode 100644 index 48b83b862eb..00000000000 --- a/nucleus/common/common-util/src/test/resources/verysimplestring.txt +++ /dev/null @@ -1 +0,0 @@ -ABC \ No newline at end of file diff --git a/nucleus/common/glassfish-api/src/main/java/org/glassfish/api/deployment/archive/WritableArchive.java b/nucleus/common/glassfish-api/src/main/java/org/glassfish/api/deployment/archive/WritableArchive.java index 9fe72a0900e..ab06f0f272b 100644 --- a/nucleus/common/glassfish-api/src/main/java/org/glassfish/api/deployment/archive/WritableArchive.java +++ b/nucleus/common/glassfish-api/src/main/java/org/glassfish/api/deployment/archive/WritableArchive.java @@ -1,4 +1,5 @@ /* + * Copyright (c) 2022 Contributors to the Eclipse Foundation * Copyright (c) 2008, 2018 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the @@ -17,7 +18,6 @@ package org.glassfish.api.deployment.archive; import java.io.IOException; -import java.io.OutputStream; import java.net.URI; import org.jvnet.hk2.annotations.Contract; @@ -31,7 +31,7 @@ public interface WritableArchive extends Archive { /** - * creates a new abstract archive with the given path + * Creates a new abstract archive with the given path * * @param uri the path to create the archive */ @@ -41,22 +41,17 @@ public interface WritableArchive extends Archive { * Close a previously returned sub archive * * @param subArchive output stream to close - * @link Archive.getSubArchive} + * @see WritableArchive#createSubArchive(String) */ void closeEntry(WritableArchive subArchive) throws IOException; /** - * Create a new entry in the archive + * Create a new entry in the archive. Caller is responsible for closing the entry. * * @param name the entry name - * @returns an @see java.io.OutputStream for a new entry in this current abstract archive. + * @return an {@link WritableArchiveEntry} for a new entry in this current abstract archive. */ - OutputStream putNextEntry(String name) throws java.io.IOException; - - /** - * closes the current entry - */ - void closeEntry() throws IOException; + WritableArchiveEntry putNextEntry(String name) throws IOException; /** * Returns an instance of this archive abstraction for an embedded archive within this archive. diff --git a/nucleus/common/glassfish-api/src/main/java/org/glassfish/api/deployment/archive/WritableArchiveEntry.java b/nucleus/common/glassfish-api/src/main/java/org/glassfish/api/deployment/archive/WritableArchiveEntry.java new file mode 100644 index 00000000000..256db7e1bf0 --- /dev/null +++ b/nucleus/common/glassfish-api/src/main/java/org/glassfish/api/deployment/archive/WritableArchiveEntry.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2022 Eclipse Foundation and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package org.glassfish.api.deployment.archive; + +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.nio.channels.Channels; +import java.nio.channels.WritableByteChannel; +import java.util.zip.ZipOutputStream; + + +/** + * @author David Matejcek + */ +public class WritableArchiveEntry extends OutputStream { + + private final ZipOutputStream archive; + private final OutputStream output; + + + /** + * @param archive owner of the archive entry + * @param output output stream to write to + */ + public WritableArchiveEntry(final ZipOutputStream archive, final OutputStream output) { + this.archive = archive; + this.output = output; + } + + + @Override + public void write(int b) throws IOException { + output.write(b); + } + + + /** + * @return output channel. No need to close it, it will be closed with this object. + */ + public WritableByteChannel getChannel() { + if (output instanceof FileOutputStream) { + return ((FileOutputStream) output).getChannel(); + } + return Channels.newChannel(output); + } + + + @Override + public void close() throws IOException { + if (archive == null) { + this.output.close(); + } else { + this.archive.flush(); + this.archive.finish(); + this.archive.closeEntry(); + } + } +} diff --git a/nucleus/common/internal-api/src/main/java/org/glassfish/internal/deployment/GenericHandler.java b/nucleus/common/internal-api/src/main/java/org/glassfish/internal/deployment/GenericHandler.java index 20302d67836..0d9155cf7ac 100644 --- a/nucleus/common/internal-api/src/main/java/org/glassfish/internal/deployment/GenericHandler.java +++ b/nucleus/common/internal-api/src/main/java/org/glassfish/internal/deployment/GenericHandler.java @@ -1,4 +1,5 @@ /* + * Copyright (c) 2022 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 @@ -16,30 +17,25 @@ package org.glassfish.internal.deployment; -import com.sun.enterprise.module.ModulesRegistry; -import org.glassfish.api.deployment.archive.ArchiveHandler; -import org.glassfish.api.deployment.archive.ReadableArchive; -import org.glassfish.api.deployment.archive.WritableArchive; -import org.glassfish.api.deployment.DeploymentContext; -import org.glassfish.hk2.api.ServiceLocator; +import com.sun.enterprise.util.io.FileUtils; + +import jakarta.inject.Inject; import java.io.IOException; import java.io.InputStream; -import java.io.BufferedInputStream; -import java.io.OutputStream; +import java.net.URI; +import java.util.ArrayList; import java.util.Enumeration; -import java.util.jar.Manifest; -import java.util.jar.JarFile; -import java.util.logging.Level; -import java.util.logging.Logger; import java.util.List; -import java.util.ArrayList; -import java.net.URI; -import java.net.URL; - -import com.sun.enterprise.util.io.FileUtils; +import java.util.jar.JarFile; +import java.util.jar.Manifest; -import jakarta.inject.Inject; +import org.glassfish.api.deployment.DeploymentContext; +import org.glassfish.api.deployment.archive.ArchiveHandler; +import org.glassfish.api.deployment.archive.ReadableArchive; +import org.glassfish.api.deployment.archive.WritableArchive; +import org.glassfish.api.deployment.archive.WritableArchiveEntry; +import org.glassfish.hk2.api.ServiceLocator; /** * Pretty generic implementation of some ArchiveHandler methods @@ -52,43 +48,35 @@ public abstract class GenericHandler implements ArchiveHandler { protected ServiceLocator habitat; /** - * Prepares the jar file to a format the ApplicationContainer is - * expecting. This could be just a pure unzipping of the jar or - * nothing at all. + * Prepares the jar file to a format the ApplicationContainer is expecting. + * This could be just a pure unzipping of the jar or nothing at all. * * @param source of the expanding * @param target of the expanding * @param context deployment context * @throws IOException when the archive is corrupted */ - public void expand(ReadableArchive source, WritableArchive target, - DeploymentContext context) throws IOException { - + @Override + public void expand(ReadableArchive source, WritableArchive target, DeploymentContext context) throws IOException { Enumeration e = source.entries(); while (e.hasMoreElements()) { String entryName = e.nextElement(); - InputStream entry = source.getEntry(entryName); - if (entry != null) { - InputStream is = new BufferedInputStream(entry); - OutputStream os = null; - try { - os = target.putNextEntry(entryName); - FileUtils.copy(is, os, source.getEntrySize(entryName)); - } finally { - if (os!=null) { - target.closeEntry(); - } - is.close(); - } + try (InputStream is = source.getEntry(entryName)) { + if (is == null) { + continue; + } + try (WritableArchiveEntry output = target.putNextEntry(entryName)) { + FileUtils.copy(is, output); + } } } - // last is manifest is existing. - Manifest m = source.getManifest(); - if (m!=null) { - OutputStream os = target.putNextEntry(JarFile.MANIFEST_NAME); - m.write(os); - target.closeEntry(); + // last is manifest if exists. + Manifest manifest = source.getManifest(); + if (manifest != null) { + try (WritableArchiveEntry output = target.putNextEntry(JarFile.MANIFEST_NAME)) { + manifest.write(output); + } } } @@ -106,6 +94,7 @@ public void expand(ReadableArchive source, WritableArchive target, * @param context deployment context * @return the default application name for the specified archive */ + @Override public String getDefaultApplicationName(ReadableArchive archive, DeploymentContext context) { // first try to get the name from ApplicationInfoProvider if @@ -118,7 +107,7 @@ public String getDefaultApplicationName(ReadableArchive archive, tracing = context.getModuleMetaData(DeploymentTracing.class); } - if (tracing!=null) { + if (tracing != null) { tracing.addMark(DeploymentTracing.Mark.APPINFO_PROVIDED); } @@ -146,6 +135,7 @@ public String getDefaultApplicationNameFromArchiveName(ReadableArchive archive) return appName; } + @Override public String getDefaultApplicationName(ReadableArchive archive) { return getDefaultApplicationName(archive, null); } @@ -157,6 +147,7 @@ public String getDefaultApplicationName(ReadableArchive archive) { * * @return null */ + @Override public String getVersionIdentifier(ReadableArchive archive){ return null; } @@ -169,6 +160,7 @@ public String getVersionIdentifier(ReadableArchive archive){ * @param archive file * @return manifest instance or null if this archive has no manifest */ + @Override public Manifest getManifest(ReadableArchive archive) throws IOException { return archive.getManifest(); } @@ -179,8 +171,9 @@ public Manifest getManifest(ReadableArchive archive) throws IOException { * @param archive file * @return classpath URIs for this archive */ + @Override public List getClassPathURIs(ReadableArchive archive) { - List uris = new ArrayList(); + List uris = new ArrayList<>(); // add the archive itself uris.add(archive.getURI()); return uris; @@ -192,6 +185,7 @@ public List getClassPathURIs(ReadableArchive archive) { * @param archive file * @return whether this archive requires annotation scanning */ + @Override public boolean requiresAnnotationScanning(ReadableArchive archive) { return true; } diff --git a/nucleus/core/kernel/src/main/java/com/sun/enterprise/v3/admin/CheckpointHelper.java b/nucleus/core/kernel/src/main/java/com/sun/enterprise/v3/admin/CheckpointHelper.java index 002be2059e6..7ab02bac22e 100644 --- a/nucleus/core/kernel/src/main/java/com/sun/enterprise/v3/admin/CheckpointHelper.java +++ b/nucleus/core/kernel/src/main/java/com/sun/enterprise/v3/admin/CheckpointHelper.java @@ -1,4 +1,5 @@ /* + * Copyright (c) 2022 Contributors to the Eclipse Foundation * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the @@ -16,12 +17,18 @@ package com.sun.enterprise.v3.admin; +import com.sun.enterprise.util.LocalStringManagerImpl; +import com.sun.enterprise.util.io.FileUtils; + +import jakarta.inject.Inject; + import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.FilenameFilter; import java.io.IOException; +import java.io.InputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.OutputStream; @@ -52,11 +59,6 @@ import org.glassfish.security.services.api.authentication.AuthenticationService; import org.jvnet.hk2.annotations.Service; -import com.sun.enterprise.util.LocalStringManagerImpl; -import com.sun.enterprise.util.io.FileUtils; - -import jakarta.inject.Inject; - /** * This class is starting point for persistent CheckpointHelper, and currently only * persists and restores AdminCommandContext with payloads in separate files. @@ -369,7 +371,9 @@ private void loadOutbound(Outbound outbound, File outboundFile) throws IOExcepti while (parts.hasNext()) { Part part = parts.next(); File sourceFile = File.createTempFile("source", "", topDir); - FileUtils.copy(part.getInputStream(), new FileOutputStream(sourceFile), Long.MAX_VALUE); + try (InputStream inputStream = part.getInputStream()) { + FileUtils.copy(inputStream, sourceFile, Long.MAX_VALUE); + } outbound.addPart(part.getContentType(), part.getName(), part.getProperties(), new FileInputStream(sourceFile)); } diff --git a/nucleus/core/kernel/src/main/java/com/sun/enterprise/v3/server/ApplicationLifecycle.java b/nucleus/core/kernel/src/main/java/com/sun/enterprise/v3/server/ApplicationLifecycle.java index 15ca4b9aa65..a919296066d 100644 --- a/nucleus/core/kernel/src/main/java/com/sun/enterprise/v3/server/ApplicationLifecycle.java +++ b/nucleus/core/kernel/src/main/java/com/sun/enterprise/v3/server/ApplicationLifecycle.java @@ -17,19 +17,23 @@ package com.sun.enterprise.v3.server; -import static com.sun.enterprise.config.serverbeans.ServerTags.IS_COMPOSITE; -import static com.sun.enterprise.util.Utility.isEmpty; -import static java.util.Collections.emptyList; -import static java.util.logging.Level.FINE; -import static java.util.logging.Level.INFO; -import static java.util.logging.Level.SEVERE; -import static java.util.logging.Level.WARNING; -import static org.glassfish.api.admin.ServerEnvironment.DEFAULT_INSTANCE_NAME; -import static org.glassfish.deployment.common.DeploymentProperties.ALT_DD; -import static org.glassfish.deployment.common.DeploymentProperties.RUNTIME_ALT_DD; -import static org.glassfish.deployment.common.DeploymentProperties.SKIP_SCAN_EXTERNAL_LIB; -import static org.glassfish.deployment.common.DeploymentUtils.getVirtualServers; -import static org.glassfish.kernel.KernelLoggerInfo.inconsistentLifecycleState; +import com.sun.enterprise.config.serverbeans.AppTenant; +import com.sun.enterprise.config.serverbeans.AppTenants; +import com.sun.enterprise.config.serverbeans.Application; +import com.sun.enterprise.config.serverbeans.ApplicationConfig; +import com.sun.enterprise.config.serverbeans.ApplicationRef; +import com.sun.enterprise.config.serverbeans.Applications; +import com.sun.enterprise.config.serverbeans.Cluster; +import com.sun.enterprise.config.serverbeans.Domain; +import com.sun.enterprise.config.serverbeans.Engine; +import com.sun.enterprise.config.serverbeans.Server; +import com.sun.enterprise.config.serverbeans.ServerTags; +import com.sun.enterprise.deploy.shared.ArchiveFactory; +import com.sun.enterprise.util.LocalStringManagerImpl; + +import jakarta.inject.Inject; +import jakarta.inject.Named; +import jakarta.inject.Singleton; import java.beans.PropertyVetoException; import java.io.BufferedInputStream; @@ -127,24 +131,19 @@ import org.jvnet.hk2.config.TransactionFailure; import org.jvnet.hk2.config.types.Property; -import com.sun.enterprise.config.serverbeans.AppTenant; -import com.sun.enterprise.config.serverbeans.AppTenants; -import com.sun.enterprise.config.serverbeans.Application; -import com.sun.enterprise.config.serverbeans.ApplicationConfig; -import com.sun.enterprise.config.serverbeans.ApplicationRef; -import com.sun.enterprise.config.serverbeans.Applications; -import com.sun.enterprise.config.serverbeans.Cluster; -import com.sun.enterprise.config.serverbeans.Domain; -import com.sun.enterprise.config.serverbeans.Engine; -import com.sun.enterprise.config.serverbeans.Server; -import com.sun.enterprise.config.serverbeans.ServerTags; -import com.sun.enterprise.deploy.shared.ArchiveFactory; -import com.sun.enterprise.deploy.shared.FileArchive; -import com.sun.enterprise.util.LocalStringManagerImpl; - -import jakarta.inject.Inject; -import jakarta.inject.Named; -import jakarta.inject.Singleton; +import static com.sun.enterprise.config.serverbeans.ServerTags.IS_COMPOSITE; +import static com.sun.enterprise.util.Utility.isEmpty; +import static java.util.Collections.emptyList; +import static java.util.logging.Level.FINE; +import static java.util.logging.Level.INFO; +import static java.util.logging.Level.SEVERE; +import static java.util.logging.Level.WARNING; +import static org.glassfish.api.admin.ServerEnvironment.DEFAULT_INSTANCE_NAME; +import static org.glassfish.deployment.common.DeploymentProperties.ALT_DD; +import static org.glassfish.deployment.common.DeploymentProperties.RUNTIME_ALT_DD; +import static org.glassfish.deployment.common.DeploymentProperties.SKIP_SCAN_EXTERNAL_LIB; +import static org.glassfish.deployment.common.DeploymentUtils.getVirtualServers; +import static org.glassfish.kernel.KernelLoggerInfo.inconsistentLifecycleState; /** * Application Loader is providing useful methods to load applications @@ -654,7 +653,7 @@ private List getExternalLibraries(DeploymentContext context) th String skipScanExternalLibProp = context.getAppProps().getProperty(SKIP_SCAN_EXTERNAL_LIB); - if (Boolean.valueOf(skipScanExternalLibProp)) { + if (Boolean.parseBoolean(skipScanExternalLibProp)) { // If we skip scanning external libraries, we should just // return an empty list here return emptyList(); @@ -1789,7 +1788,7 @@ private ExtendedDeploymentContext getContext(ExtendedDeploymentContext initial, DeploymentContextBuilder copy = new DeploymentContextBuidlerImpl(builder); - ReadableArchive archive = getArchive(copy); + final ReadableArchive archive = getArchive(copy); copy.source(archive); if (initial == null) { @@ -1834,25 +1833,26 @@ private ExtendedDeploymentContext getContext(ExtendedDeploymentContext initial, * file in the earlier deployment had been locked. Warn but do not fail in such a case. */ LOG.fine(localStrings.getLocalString("deploy.cannotcreateexpansiondir", - "Error while creating directory for jar expansion: {0}", expansionDir)); + "Error while creating directory for jar expansion: {0}", expansionDir)); } try { Long start = System.currentTimeMillis(); - final WritableArchive expandedArchive = archiveFactory.createArchive(expansionDir); - archiveHandler.expand(archive, expandedArchive, initial); - if (LOG.isLoggable(FINE)) { - LOG.fine("Deployment expansion took " + (System.currentTimeMillis() - start)); - } + try (WritableArchive expandedArchive = archiveFactory.createArchive(expansionDir)) { + archiveHandler.expand(archive, expandedArchive, initial); + if (LOG.isLoggable(FINE)) { + LOG.fine("Deployment expansion took " + (System.currentTimeMillis() - start)); + } - // Close the JAR archive before losing the reference to it or else the JAR remains locked. - try { - archive.close(); - } catch (IOException e) { - LOG.log(SEVERE, KernelLoggerInfo.errorClosingArtifact, new Object[] { archive.getURI().getSchemeSpecificPart(), e }); - throw e; + // Close the JAR archive before losing the reference to it or else the JAR remains locked. + try { + // FIXME: There is no guarantee that the archive will be closed. + archive.close(); + } catch (IOException e) { + LOG.log(SEVERE, KernelLoggerInfo.errorClosingArtifact, new Object[] { archive.getURI().getSchemeSpecificPart(), e }); + throw e; + } + initial.setSource((ReadableArchive) expandedArchive); } - archive = (FileArchive) expandedArchive; - initial.setSource(archive); } catch (IOException e) { LOG.log(SEVERE, KernelLoggerInfo.errorExpandingFile, e); throw e; @@ -2013,26 +2013,22 @@ private void addFileToZip(final ZipOutputStream zipOS, final File baseDir, final final String entryName = baseDir.toURI().relativize(f.toURI()).getPath(); final ZipEntry entry = new ZipEntry(entryName); zipOS.putNextEntry(entry); - if (!f.isDirectory()) { + if (f.isDirectory()) { + // A directory entry has no content itself. + zipOS.closeEntry(); + for (File subFile : f.listFiles()) { + addFileToZip(zipOS, baseDir, subFile); + } + } else { final byte[] buffer = new byte[1024]; - final InputStream is = new BufferedInputStream(new FileInputStream(f)); - int bytesRead; - try { + try (final InputStream is = new BufferedInputStream(new FileInputStream(f))) { + int bytesRead; while ((bytesRead = is.read(buffer)) != -1) { zipOS.write(buffer, 0, bytesRead); } } finally { - is.close(); zipOS.closeEntry(); } - } else { - /* - * A directory entry has no content itself. - */ - zipOS.closeEntry(); - for (File subFile : f.listFiles()) { - addFileToZip(zipOS, baseDir, subFile); - } } } @@ -2121,7 +2117,7 @@ public void validateSpecifiedTarget(String target) { @Override public boolean isAppEnabled(Application app) { - if (Boolean.valueOf(app.getEnabled())) { + if (Boolean.parseBoolean(app.getEnabled())) { ApplicationRef appRef = server.getApplicationRef(app.getName()); if (appRef != null && Boolean.valueOf(appRef.getEnabled())) { return true; diff --git a/nucleus/core/kernel/src/main/java/com/sun/enterprise/v3/server/ApplicationLoaderService.java b/nucleus/core/kernel/src/main/java/com/sun/enterprise/v3/server/ApplicationLoaderService.java index 9113aaca4fc..b25cc611400 100644 --- a/nucleus/core/kernel/src/main/java/com/sun/enterprise/v3/server/ApplicationLoaderService.java +++ b/nucleus/core/kernel/src/main/java/com/sun/enterprise/v3/server/ApplicationLoaderService.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 Contributors to the Eclipse Foundation. + * Copyright (c) 2022, 2024 Contributors to the Eclipse Foundation. * Copyright (c) 2006, 2018 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the @@ -17,6 +17,22 @@ package com.sun.enterprise.v3.server; +import com.sun.enterprise.config.serverbeans.AppTenant; +import com.sun.enterprise.config.serverbeans.Application; +import com.sun.enterprise.config.serverbeans.ApplicationRef; +import com.sun.enterprise.config.serverbeans.Applications; +import com.sun.enterprise.config.serverbeans.Domain; +import com.sun.enterprise.config.serverbeans.Server; +import com.sun.enterprise.config.serverbeans.ServerTags; +import com.sun.enterprise.config.serverbeans.SystemApplications; +import com.sun.enterprise.deploy.shared.ArchiveFactory; +import com.sun.enterprise.util.io.FileUtils; +import com.sun.enterprise.v3.common.HTMLActionReporter; + +import jakarta.inject.Inject; +import jakarta.inject.Named; +import jakarta.inject.Provider; + import java.io.File; import java.io.IOException; import java.net.URI; @@ -36,10 +52,10 @@ import org.glassfish.api.StartupRunLevel; import org.glassfish.api.admin.ServerEnvironment; import org.glassfish.api.deployment.DeployCommandParameters; -import org.glassfish.api.deployment.DeploymentContext; import org.glassfish.api.deployment.UndeployCommandParameters; import org.glassfish.api.deployment.archive.ArchiveHandler; import org.glassfish.api.deployment.archive.ReadableArchive; +import org.glassfish.api.deployment.archive.WritableArchive; import org.glassfish.api.event.EventListener.Event; import org.glassfish.api.event.EventTypes; import org.glassfish.api.event.Events; @@ -68,22 +84,6 @@ import org.jvnet.hk2.annotations.Optional; import org.jvnet.hk2.annotations.Service; -import com.sun.enterprise.config.serverbeans.AppTenant; -import com.sun.enterprise.config.serverbeans.Application; -import com.sun.enterprise.config.serverbeans.ApplicationRef; -import com.sun.enterprise.config.serverbeans.Applications; -import com.sun.enterprise.config.serverbeans.Domain; -import com.sun.enterprise.config.serverbeans.Server; -import com.sun.enterprise.config.serverbeans.ServerTags; -import com.sun.enterprise.config.serverbeans.SystemApplications; -import com.sun.enterprise.deploy.shared.ArchiveFactory; -import com.sun.enterprise.util.io.FileUtils; -import com.sun.enterprise.v3.common.HTMLActionReporter; - -import jakarta.inject.Inject; -import jakarta.inject.Named; -import jakarta.inject.Provider; - /** * This service is responsible for loading all deployed applications... * @@ -144,7 +144,7 @@ public class ApplicationLoaderService implements org.glassfish.hk2.api.PreDestro private String deploymentTracingEnabled = null; - private Map appOrderInfoMap = new HashMap<>(); + private final Map appOrderInfoMap = new HashMap<>(); private int appOrder = 0; /** @@ -200,7 +200,7 @@ public void postConstruct() { for (Application systemApp : systemApplications.getApplications()) { // check to see if we need to load up this system application - if (Boolean.valueOf(systemApp.getDeployProperties().getProperty + if (Boolean.parseBoolean(systemApp.getDeployProperties().getProperty (ServerTags.LOAD_SYSTEM_APP_ON_STARTUP))) { if (deployment.isAppEnabled(systemApp) || loadAppOnDAS(systemApp.getName())) { Integer order = appOrderInfoMap.get(systemApp.getName()); @@ -291,9 +291,10 @@ public void postConstruct() { ArchiveHandler handler = deployment.getArchiveHandler(sourceArchive); final String appName = handler.getDefaultApplicationName(sourceArchive); DeploymentContextImpl dummyContext = new DeploymentContextImpl(report, logger, sourceArchive, parameters, env); - handler.expand(sourceArchive, archiveFactoryProvider.get().createArchive(tmpDir), dummyContext); - sourceArchive = - archiveFactoryProvider.get().openArchive(tmpDir); + try (WritableArchive output = archiveFactoryProvider.get().createArchive(tmpDir)) { + handler.expand(sourceArchive, output, dummyContext); + } + sourceArchive = archiveFactoryProvider.get().openArchive(tmpDir); logger.log(Level.INFO, KernelLoggerInfo.sourceNotDirectory, tmpDir.getAbsolutePath()); parameters.name = appName; } @@ -353,7 +354,7 @@ public void processApplication(Application app, ApplicationRef appRef) { final String appName = app.getName(); // lifecycle modules are loaded separately - if (Boolean.valueOf(app.getDeployProperties().getProperty + if (Boolean.parseBoolean(app.getDeployProperties().getProperty (ServerTags.IS_LIFECYCLE))) { return; } diff --git a/nucleus/core/kernel/src/main/java/com/sun/enterprise/v3/server/UpgradeStartup.java b/nucleus/core/kernel/src/main/java/com/sun/enterprise/v3/server/UpgradeStartup.java index e6c597a8f31..f3970cf531a 100644 --- a/nucleus/core/kernel/src/main/java/com/sun/enterprise/v3/server/UpgradeStartup.java +++ b/nucleus/core/kernel/src/main/java/com/sun/enterprise/v3/server/UpgradeStartup.java @@ -1,4 +1,5 @@ /* + * Copyright (c) 2022 Contributors to the Eclipse Foundation * Copyright (c) 2008, 2018 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the @@ -16,8 +17,22 @@ package com.sun.enterprise.v3.server; +import com.sun.enterprise.config.serverbeans.Application; +import com.sun.enterprise.config.serverbeans.Applications; +import com.sun.enterprise.config.serverbeans.Domain; +import com.sun.enterprise.config.serverbeans.Server; +import com.sun.enterprise.config.serverbeans.ServerTags; +import com.sun.enterprise.deploy.shared.ArchiveFactory; +import com.sun.enterprise.module.bootstrap.ModuleStartup; +import com.sun.enterprise.module.bootstrap.StartupContext; +import com.sun.enterprise.util.StringUtils; +import com.sun.enterprise.util.io.FileUtils; +import com.sun.enterprise.v3.common.DoNothingActionReporter; + +import jakarta.inject.Inject; +import jakarta.inject.Named; + import java.beans.PropertyVetoException; -import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; @@ -44,6 +59,7 @@ import org.glassfish.api.deployment.DeployCommandParameters; import org.glassfish.api.deployment.archive.ReadableArchive; import org.glassfish.api.deployment.archive.WritableArchive; +import org.glassfish.api.deployment.archive.WritableArchiveEntry; import org.glassfish.deployment.common.DeploymentProperties; import org.glassfish.hk2.api.IterableProvider; import org.glassfish.internal.api.DomainUpgrade; @@ -57,21 +73,6 @@ import org.jvnet.hk2.config.SingleConfigCode; import org.jvnet.hk2.config.TransactionFailure; -import com.sun.enterprise.config.serverbeans.Application; -import com.sun.enterprise.config.serverbeans.Applications; -import com.sun.enterprise.config.serverbeans.Domain; -import com.sun.enterprise.config.serverbeans.Server; -import com.sun.enterprise.config.serverbeans.ServerTags; -import com.sun.enterprise.deploy.shared.ArchiveFactory; -import com.sun.enterprise.module.bootstrap.ModuleStartup; -import com.sun.enterprise.module.bootstrap.StartupContext; -import com.sun.enterprise.util.StringUtils; -import com.sun.enterprise.util.io.FileUtils; -import com.sun.enterprise.v3.common.DoNothingActionReporter; - -import jakarta.inject.Inject; -import jakarta.inject.Named; - /** * Very simple ModuleStartup that basically force an immediate shutdown. * When start() is invoked, the upgrade of the domain.xml has already been @@ -180,7 +181,7 @@ public Object run(ConfigBeanProxy... configBeanProxies) throws PropertyVetoExcep // redeploy all existing applications for (Application app : applications.getApplications()) { // we don't need to redeploy lifecycle modules - if (Boolean.valueOf(app.getDeployProperties().getProperty + if (Boolean.parseBoolean(app.getDeployProperties().getProperty (ServerTags.IS_LIFECYCLE))) { continue; } @@ -327,8 +328,7 @@ private boolean redeployApp(Application app) { deployParams.properties.remove(MODULE_TYPE); // add the compatibility property so the applications are // upgraded/redeployed in a backward compatible way - deployParams.properties.setProperty( - DeploymentProperties.COMPATIBILITY, "v2"); + deployParams.properties.setProperty(DeploymentProperties.COMPATIBILITY, "v2"); // now override the ones needed for the upgrade deployParams.enabled = null; @@ -389,166 +389,130 @@ private File repackageApplication(File appDir, String targetParentDir, String suffix) throws IOException { String appName = appDir.getName(); - ReadableArchive source = archiveFactory.openArchive(appDir); - File tempEar = new File(targetParentDir, appName + suffix); - if (tempEar.exists()) { boolean isDeleted = tempEar.delete(); if (!isDeleted) { logger.log(Level.WARNING, "Error in deleting file " + tempEar.getAbsolutePath()); } } - - WritableArchive target = archiveFactory.createArchive("jar", tempEar); - - Collection directoryEntries = source.getDirectories(); - List subModuleEntries = new ArrayList<>(); - List entriesToExclude = new ArrayList<>(); - - // first put all the sub module jars to the target archive - for (String directoryEntry : directoryEntries) { - if (directoryEntry.endsWith("_jar") || - directoryEntry.endsWith("_war") || - directoryEntry.endsWith("_rar")) { - subModuleEntries.add(directoryEntry); - File moduleJar = processModule(new File( - appDir, directoryEntry), targetParentDir, null); - OutputStream os = null; - InputStream is = new BufferedInputStream( - new FileInputStream(moduleJar)); - try { - os = target.putNextEntry(moduleJar.getName()); - FileUtils.copy(is, os, moduleJar.length()); - } finally { - if (os!=null) { - target.closeEntry(); + try (ReadableArchive source = archiveFactory.openArchive(appDir); + WritableArchive target = archiveFactory.createArchive("jar", tempEar)) { + + Collection directoryEntries = source.getDirectories(); + List subModuleEntries = new ArrayList<>(); + List entriesToExclude = new ArrayList<>(); + + // first put all the sub module jars to the target archive + for (String directoryEntry : directoryEntries) { + if (directoryEntry.endsWith("_jar") || directoryEntry.endsWith("_war") + || directoryEntry.endsWith("_rar")) { + subModuleEntries.add(directoryEntry); + File moduleJar = processModule(new File(appDir, directoryEntry), targetParentDir, null); + try (InputStream is = new FileInputStream(moduleJar); + OutputStream os = target.putNextEntry(moduleJar.getName())) { + FileUtils.copy(is, os); } - is.close(); } } - } - // now find all the entries we should exclude to copy to the target - // basically all sub module entries should be excluded - for (String subModuleEntry : subModuleEntries) { - Enumeration ee = source.entries(subModuleEntry); - while (ee.hasMoreElements()) { - String eeEntryName = ee.nextElement(); - entriesToExclude.add(eeEntryName); + // now find all the entries we should exclude to copy to the target + // basically all sub module entries should be excluded + for (String subModuleEntry : subModuleEntries) { + Enumeration ee = source.entries(subModuleEntry); + while (ee.hasMoreElements()) { + String eeEntryName = ee.nextElement(); + entriesToExclude.add(eeEntryName); + } } - } - // now copy the rest of the entries - Enumeration e = source.entries(); - while (e.hasMoreElements()) { - String entryName = e.nextElement(); - if (! entriesToExclude.contains(entryName)) { - InputStream sis = source.getEntry(entryName); + // now copy the rest of the entries + Enumeration e = source.entries(); + while (e.hasMoreElements()) { + String entryName = e.nextElement(); + if (entriesToExclude.contains(entryName)) { + continue; + } if (isSigFile(entryName)) { - logger.log(Level.INFO, "Excluding signature file: " - + entryName + " from repackaged application: " + - appName + "\n"); + logger.log(Level.INFO, "Excluding signature file: {0} from repackaged application: {1}", + new Object[] {entryName, appName}); continue; } - if (sis != null) { - InputStream is = new BufferedInputStream(sis); - OutputStream os = null; - try { - os = target.putNextEntry(entryName); - FileUtils.copy(is, os, source.getEntrySize(entryName)); - } finally { - if (os!=null) { - target.closeEntry(); - } - is.close(); + try (InputStream sis = source.getEntry(entryName)) { + if (sis == null) { + continue; + } + try (WritableArchiveEntry os = target.putNextEntry(entryName)) { + FileUtils.copy(sis, os); } } } - } - // last is manifest if existing. - Manifest m = source.getManifest(); - if (m!=null) { - processManifest(m, appName); - OutputStream os = target.putNextEntry(JarFile.MANIFEST_NAME); - m.write(os); - target.closeEntry(); + // last is manifest if existing. + Manifest m = source.getManifest(); + if (m != null) { + processManifest(m, appName); + try (WritableArchiveEntry os = target.putNextEntry(JarFile.MANIFEST_NAME)) { + m.write(os); + } + } } - - source.close(); - target.close(); - return tempEar; } + private File repackageStandaloneModule(File moduleDirName, String targetParentDir, String suffix) throws IOException { return processModule(moduleDirName, targetParentDir, suffix); } // repackage a module and return it as a jar file - private File processModule(File moduleDir, String targetParentDir, - String suffix) throws IOException { - + private File processModule(File moduleDir, String targetParentDir, String suffix) throws IOException { String moduleName = moduleDir.getName(); // sub module in ear case if (moduleName.endsWith("_jar") || moduleName.endsWith("_war") || moduleName.endsWith("_rar")) { - suffix = "." + moduleName.substring(moduleName.length() - 3); + suffix = "." + moduleName.substring(moduleName.length() - 3); moduleName = moduleName.substring(0, moduleName.lastIndexOf('_')); } - ReadableArchive source = archiveFactory.openArchive(moduleDir); - File tempJar = new File(targetParentDir, moduleName + suffix); - if (tempJar.exists()) { boolean isDeleted = tempJar.delete(); - if ( !isDeleted) { + if (!isDeleted) { logger.log(Level.WARNING, "Error in deleting file " + tempJar.getAbsolutePath()); } } - - WritableArchive target = archiveFactory.createArchive("jar", tempJar); - - Enumeration e = source.entries(); - while (e.hasMoreElements()) { - String entryName = e.nextElement(); - if (isSigFile(entryName)) { - logger.log(Level.INFO, "Excluding signature file: " - + entryName + " from repackaged module: " + moduleName + - "\n"); - continue; - } - InputStream sis = source.getEntry(entryName); - if (sis != null) { - InputStream is = new BufferedInputStream(sis); - OutputStream os = null; - try { - os = target.putNextEntry(entryName); - FileUtils.copy(is, os, source.getEntrySize(entryName)); - } finally { - if (os!=null) { - target.closeEntry(); + try (ReadableArchive source = archiveFactory.openArchive(moduleDir); + WritableArchive target = archiveFactory.createArchive("jar", tempJar)) { + Enumeration e = source.entries(); + while (e.hasMoreElements()) { + String entryName = e.nextElement(); + if (isSigFile(entryName)) { + logger.log(Level.INFO, + "Excluding signature file: " + entryName + " from repackaged module: " + moduleName + "\n"); + continue; + } + try (InputStream sis = source.getEntry(entryName)) { + if (sis == null) { + continue; + } + try (OutputStream os = target.putNextEntry(entryName)) { + FileUtils.copy(sis, os); } - is.close(); } } - } - // last is manifest if existing. - Manifest m = source.getManifest(); - if (m!=null) { - processManifest(m, moduleName); - OutputStream os = target.putNextEntry(JarFile.MANIFEST_NAME); - m.write(os); - target.closeEntry(); + // last is manifest if existing. + Manifest manifest = source.getManifest(); + if (manifest != null) { + processManifest(manifest, moduleName); + try (OutputStream os = target.putNextEntry(JarFile.MANIFEST_NAME)) { + manifest.write(os); + } + } } - source.close(); - target.close(); - return tempJar; } diff --git a/nucleus/deployment/admin/src/main/java/org/glassfish/deployment/admin/InstanceDeployCommand.java b/nucleus/deployment/admin/src/main/java/org/glassfish/deployment/admin/InstanceDeployCommand.java index e3a6235cb41..8a2e44a15ff 100644 --- a/nucleus/deployment/admin/src/main/java/org/glassfish/deployment/admin/InstanceDeployCommand.java +++ b/nucleus/deployment/admin/src/main/java/org/glassfish/deployment/admin/InstanceDeployCommand.java @@ -1,4 +1,5 @@ /* + * Copyright (c) 2022 Contributors to the Eclipse Foundation * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the @@ -18,6 +19,7 @@ import java.io.File; import java.io.IOException; +import java.io.InputStream; import java.net.URI; import java.util.ArrayList; import java.util.Calendar; @@ -57,7 +59,6 @@ import com.sun.enterprise.config.serverbeans.Applications; import com.sun.enterprise.config.serverbeans.Application; import com.sun.enterprise.config.serverbeans.Domain; -import java.io.FileOutputStream; import java.util.Collection; import org.glassfish.api.admin.AccessRequired.AccessCheck; import org.glassfish.api.admin.AdminCommandSecurity; @@ -108,7 +109,7 @@ public class InstanceDeployCommand extends InstanceDeployCommandParameters @Override public Collection getAccessChecks() { - final List accessChecks = new ArrayList(); + final List accessChecks = new ArrayList<>(); accessChecks.add(new AccessCheck(DeploymentCommandUtils.getTargetResourceNameForNewAppRef(domain, target), "write")); return accessChecks; } @@ -273,16 +274,14 @@ private void processGeneratedContent( final URI outputFileURI = Util.resolve(baseURI, zipEntry.getName()); final File outputFile = new File(outputFileURI); if (zipEntry.isDirectory()) { - if ( ! outputFile.exists() && ! outputFile.mkdirs()) { + if (!outputFile.exists() && !outputFile.mkdirs()) { throw new IOException(localStrings.getLocalString("instancedeploy.command.errcredir", - "Error creating directory {0}. No further information about the failure is available.", baseDir.getAbsolutePath())); + "Error creating directory {0}. No further information about the failure is available.", + baseDir.getAbsolutePath())); } } else { - final FileOutputStream os = new FileOutputStream(outputFile); - try { - FileUtils.copy(zipFile.getInputStream(zipEntry), os, zipEntry.getSize()); - } catch (IOException e) { - os.close(); + try (InputStream inputStream = zipFile.getInputStream(zipEntry)) { + FileUtils.copy(inputStream, outputFile, zipEntry.getSize()); } } } diff --git a/nucleus/deployment/common/src/main/java/com/sun/enterprise/deploy/shared/ArchiveFactory.java b/nucleus/deployment/common/src/main/java/com/sun/enterprise/deploy/shared/ArchiveFactory.java index dcceff69889..29e93c46de6 100644 --- a/nucleus/deployment/common/src/main/java/com/sun/enterprise/deploy/shared/ArchiveFactory.java +++ b/nucleus/deployment/common/src/main/java/com/sun/enterprise/deploy/shared/ArchiveFactory.java @@ -53,10 +53,13 @@ public class ArchiveFactory { public static final Logger deplLogger = org.glassfish.deployment.common.DeploymentContextImpl.deplLogger; - @LogMessageInfo(message = "Cannot find an archive implementation for {0}", cause = "The type of archive being created is not supported.", action = "Determine the type of archive requested to see whether another type can be used.", level = "SEVERE") + @LogMessageInfo( + message = "Cannot find an archive implementation for {0}", + cause = "The type of archive being created is not supported.", + action = "Determine the type of archive requested to see whether another type can be used.", + level = "SEVERE") private static final String IMPLEMENTATION_NOT_FOUND = "NCLS-DEPLOYMENT-00021"; - @Inject ServiceLocator serviceLocator; diff --git a/nucleus/deployment/common/src/main/java/com/sun/enterprise/deploy/shared/FileArchive.java b/nucleus/deployment/common/src/main/java/com/sun/enterprise/deploy/shared/FileArchive.java index d2c1ca22520..eaf5a35f92e 100644 --- a/nucleus/deployment/common/src/main/java/com/sun/enterprise/deploy/shared/FileArchive.java +++ b/nucleus/deployment/common/src/main/java/com/sun/enterprise/deploy/shared/FileArchive.java @@ -17,8 +17,12 @@ package com.sun.enterprise.deploy.shared; +import com.sun.enterprise.deployment.deploy.shared.Util; +import com.sun.enterprise.util.io.FileUtils; + +import jakarta.inject.Inject; + import java.io.BufferedInputStream; -import java.io.BufferedOutputStream; import java.io.File; import java.io.FileFilter; import java.io.FileInputStream; @@ -28,7 +32,6 @@ import java.io.IOException; import java.io.InputStream; import java.io.LineNumberReader; -import java.io.OutputStream; import java.io.PrintStream; import java.net.URI; import java.nio.file.Files; @@ -44,19 +47,15 @@ import java.util.jar.Manifest; import java.util.logging.Level; import java.util.logging.Logger; - import org.glassfish.api.deployment.archive.Archive; import org.glassfish.api.deployment.archive.ReadableArchive; import org.glassfish.api.deployment.archive.WritableArchive; +import org.glassfish.api.deployment.archive.WritableArchiveEntry; +import org.glassfish.deployment.common.DeploymentContextImpl; import org.glassfish.hk2.api.PerLookup; import org.glassfish.logging.annotation.LogMessageInfo; import org.jvnet.hk2.annotations.Service; -import com.sun.enterprise.deployment.deploy.shared.Util; -import com.sun.enterprise.util.io.FileUtils; - -import jakarta.inject.Inject; - /** * This implementation of the Archive interface maps to a directory/file structure. *

@@ -87,7 +86,7 @@ @PerLookup public class FileArchive extends AbstractReadableArchive implements WritableArchive { - public static final Logger deplLogger = org.glassfish.deployment.common.DeploymentContextImpl.deplLogger; + private static final Logger deplLogger = DeploymentContextImpl.deplLogger; @LogMessageInfo(message = "Attempt to list files in {0} failed, perhaps because that is not a valid directory or because file permissions do not allow GlassFish to access it", level = "WARNING") private static final String FILE_LIST_FAILURE = "NCLS-DEPLOYMENT-00022"; @@ -98,14 +97,11 @@ public class FileArchive extends AbstractReadableArchive implements WritableArch private final static Level DEBUG_LEVEL = Level.FINE; @Inject - ArchiveFactory archiveFactory; + private ArchiveFactory archiveFactory; // the archive abstraction directory. - File archive; - URI uri; - - // the currently opened entry - OutputStream os; + private File archive; + private URI uri; /* * tracks stale files in the archive and filters the archive's contents to exclude stale entries @@ -241,7 +237,7 @@ public Enumeration entries() { */ @Override public Collection getDirectories() throws IOException { - List results = new ArrayList(); + List results = new ArrayList<>(); if (archive != null) { for (File file : archive.listFiles()) { if (file.isDirectory() && isEntryValid(file)) { @@ -258,7 +254,7 @@ public Collection getDirectories() throws IOException { * not count their entries as part of this archive */ public Enumeration entries(Enumeration embeddedArchives) { - List nameList = new ArrayList(); + List nameList = new ArrayList<>(); List massagedNames = new ArrayList(); while (embeddedArchives.hasMoreElements()) { String subArchiveName = (String) embeddedArchives.nextElement(); @@ -279,7 +275,7 @@ public Enumeration entries(Enumeration embeddedArchives) { public Enumeration entries(String prefix) { prefix = prefix.replace('/', File.separatorChar); File file = new File(archive, prefix); - List namesList = new ArrayList(); + List namesList = new ArrayList<>(); getListOfFiles(file, namesList, null); return Collections.enumeration(namesList); } @@ -454,26 +450,10 @@ public boolean renameTo(String name) { return FileUtils.renameFile(archive, new File(name)); } - /** - * Closes the current entry - */ - @Override - public void closeEntry() throws IOException { - if (os != null) { - os.flush(); - os.close(); - os = null; - } - } - /** - * @returns an @see java.io.OutputStream for a new entry in this current abstract archive. - * @param name the entry name - */ @Override - public OutputStream putNextEntry(String name) throws java.io.IOException { + public WritableArchiveEntry putNextEntry(String name) throws java.io.IOException { name = name.replace('/', File.separatorChar); - File newFile = new File(archive, name); if (newFile.exists()) { if (!deleteEntry(name, false /* isLogging */) && uri != null) { @@ -491,8 +471,7 @@ public OutputStream putNextEntry(String name) throws java.io.IOException { } } staleFileManager().recordValidEntry(newFile); - os = new BufferedOutputStream(new FileOutputStream(newFile)); - return os; + return new WritableArchiveEntry(null, new FileOutputStream(newFile)); } /** @@ -654,14 +633,14 @@ private boolean deleteDir(File directory) throws IOException { */ if (!Files.isSymbolicLink(directory.toPath())) { File[] entries = directory.listFiles(); - for (int i = 0; i < entries.length; i++) { - if (entries[i].isDirectory()) { - allDeletesSucceeded &= deleteDir(entries[i]); + for (File entry : entries) { + if (entry.isDirectory()) { + allDeletesSucceeded &= deleteDir(entry); } else { - if (!entries[i].equals(StaleFileManager.Util.markerFile(archive))) { - final boolean fileDeleteOK = FileUtils.deleteFileWithWaitLoop(entries[i]); + if (!entry.equals(StaleFileManager.Util.markerFile(archive))) { + final boolean fileDeleteOK = FileUtils.deleteFileWithWaitLoop(entry); if (fileDeleteOK) { - myStaleFileManager().recordDeletedEntry(entries[i]); + myStaleFileManager().recordDeletedEntry(entry); } allDeletesSucceeded &= fileDeleteOK; } @@ -690,8 +669,9 @@ private void getListOfFiles(File directory, List files, List embeddedArc * @param logger logger to which to report inability to get the list of files from the directory */ void getListOfFiles(File directory, List files, List embeddedArchives, final Logger logger) { - if (archive == null || directory == null || !directory.isDirectory()) + if (archive == null || directory == null || !directory.isDirectory()) { return; + } final File[] fileList = directory.listFiles(); if (fileList == null) { deplLogger.log(Level.WARNING, FILE_LIST_FAILURE, directory.getAbsolutePath()); @@ -733,7 +713,7 @@ private boolean deleteEntry(String name, final boolean isLogging) { /** * API which FileArchive methods should use for dealing with the StaleFileManager implementation. */ - public static interface StaleFileManager { + public interface StaleFileManager { /** * Returns whether the specified file is valid - that is, is dated after the archive was created. @@ -823,13 +803,13 @@ public static void markDeletedArchive(final File archiveFile) { * @return Iterator over the contained files */ private static Iterator findFiles(final File dir) { - return new Iterator() { + return new Iterator<>() { private final List fileList; private final ListIterator fileListIt; { - fileList = new ArrayList(Arrays.asList(dir.listFiles(new MarkerExcluderFileFilter()))); + fileList = new ArrayList<>(Arrays.asList(dir.listFiles(new MarkerExcluderFileFilter()))); fileListIt = fileList.listIterator(); } @@ -953,7 +933,7 @@ private StaleFileManagerImpl(final File archive) throws FileNotFoundException, I * @throws IOException in case of errors reading the marker file */ private static Collection readStaleEntryNames(final File markerFile) throws FileNotFoundException, IOException { - final Collection result = new ArrayList(); + final Collection result = new ArrayList<>(); if (!markerFile.exists()) { return result; } diff --git a/nucleus/deployment/common/src/main/java/com/sun/enterprise/deployment/deploy/shared/MemoryMappedArchive.java b/nucleus/deployment/common/src/main/java/com/sun/enterprise/deployment/deploy/shared/MemoryMappedArchive.java index 19318de67c4..89cb582fabe 100644 --- a/nucleus/deployment/common/src/main/java/com/sun/enterprise/deployment/deploy/shared/MemoryMappedArchive.java +++ b/nucleus/deployment/common/src/main/java/com/sun/enterprise/deployment/deploy/shared/MemoryMappedArchive.java @@ -1,4 +1,5 @@ /* + * Copyright (c) 2022 Contributors to the Eclipse Foundation * Copyright (c) 2006, 2018 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the @@ -14,44 +15,43 @@ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 */ -/* - * MemoryMappedArchive.java - * - * Created on September 6, 2002, 2:58 PM - */ - package com.sun.enterprise.deployment.deploy.shared; -import com.sun.enterprise.util.shared.ArchivistUtils; -import org.glassfish.api.deployment.archive.ReadableArchive; -import org.jvnet.hk2.annotations.Service; -import org.glassfish.hk2.api.PerLookup; - - -import java.io.*; +import com.sun.enterprise.util.io.FileUtils; +import java.io.BufferedInputStream; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; import java.net.URI; +import java.util.Collection; import java.util.Enumeration; import java.util.Vector; -import java.util.Collection; +import java.util.jar.JarEntry; import java.util.jar.JarInputStream; import java.util.jar.JarOutputStream; import java.util.jar.Manifest; -import java.util.jar.JarEntry; -import java.util.zip.ZipEntry; import java.util.logging.Level; import java.util.logging.Logger; +import java.util.zip.ZipEntry; + +import org.glassfish.api.deployment.archive.ReadableArchive; +import org.glassfish.hk2.api.PerLookup; +import org.jvnet.hk2.annotations.Service; /** - * - * @author Jerome Dochez + * @author Jerome Dochez 2002 */ @Service @PerLookup public class MemoryMappedArchive extends JarArchive implements ReadableArchive { private URI uri; + private byte[] file; - byte[] file; /** Creates a new instance of MemoryMappedArchive */ protected MemoryMappedArchive() { @@ -73,53 +73,50 @@ public byte[] getByteArray() { private void read(InputStream is) throws IOException{ ByteArrayOutputStream baos = new ByteArrayOutputStream(); - ArchivistUtils.copy(is,baos); + FileUtils.copy(is, baos); file = baos.toByteArray(); - } + @Override public void open(URI uri) throws IOException { File in = new File(uri); if (!in.exists()) { throw new FileNotFoundException(uri.getSchemeSpecificPart()); } - FileInputStream is = null; - try { - is = new FileInputStream(in); + try (FileInputStream is = new FileInputStream(in)) { read(is); - } finally { - if (is != null) { - is.close(); - } } } // copy constructor public MemoryMappedArchive(ReadableArchive source) throws IOException { ByteArrayOutputStream baos = new ByteArrayOutputStream(); - JarOutputStream jos = new JarOutputStream(baos); - for (Enumeration elements = source.entries();elements.hasMoreElements();) { - String elementName = (String) elements.nextElement(); - InputStream is = source.getEntry(elementName); - jos.putNextEntry(new ZipEntry(elementName)); - ArchivistUtils.copyWithoutClose(is, jos); - is.close(); - jos.flush(); - jos.closeEntry(); + try (JarOutputStream jos = new JarOutputStream(baos)) { + for (Enumeration elements = source.entries(); elements.hasMoreElements();) { + String elementName = elements.nextElement(); + try (InputStream is = source.getEntry(elementName)) { + jos.putNextEntry(new ZipEntry(elementName)); + FileUtils.copy(is, jos); + } finally { + jos.flush(); + jos.closeEntry(); + } + } } - jos.close(); file = baos.toByteArray(); } /** * close the abstract archive */ + @Override public void close() throws IOException { } /** * delete the archive */ + @Override public boolean delete() { return false; } @@ -128,11 +125,13 @@ public boolean delete() { * @return an @see java.util.Enumeration of entries in this abstract * archive */ + @Override public Enumeration entries() { return entries(false).elements(); } + @Override public Collection getDirectories() throws IOException { return entries(true); } @@ -169,6 +168,7 @@ public Enumeration entries(Enumeration embeddedArchives) { /** * @return true if this archive exists */ + @Override public boolean exists() { return false; } @@ -184,10 +184,12 @@ public String getPath() { * Get the size of the archive * @return tje the size of this archive or -1 on error */ + @Override public long getArchiveSize() throws NullPointerException, SecurityException { return(file.length); } + @Override public URI getURI() { return uri; } @@ -201,6 +203,7 @@ public void setURI(final URI uri) { * * @param name the name of the embedded archive. */ + @Override public ReadableArchive getSubArchive(String name) throws IOException { InputStream is = getEntry(name); if (is!=null) { @@ -218,6 +221,7 @@ public ReadableArchive getSubArchive(String name) throws IOException { * @param name the file name relative to the root of the module. * @return the existence the given entry name. */ + @Override public boolean exists(String name) throws IOException { return (getEntry(name) != null); } @@ -227,16 +231,19 @@ public boolean exists(String name) throws IOException { * the current abstract archive * @param name the entry name */ + @Override public InputStream getEntry(String name) throws IOException { JarInputStream jis = new JarInputStream(new ByteArrayInputStream(file)); ZipEntry ze; while ((ze=jis.getNextEntry())!=null) { - if (ze.getName().equals(name)) + if (ze.getName().equals(name)) { return new BufferedInputStream(jis); + } } return null; } + @Override public JarEntry getJarEntry(String name) { try { JarInputStream jis = new JarInputStream(new ByteArrayInputStream(file)); @@ -258,6 +265,7 @@ public JarEntry getJarEntry(String name) { * @param name the entry name * @return the entry size */ + @Override public long getEntrySize(String name) { try { JarInputStream jis = new JarInputStream(new ByteArrayInputStream(file)); @@ -276,6 +284,7 @@ public long getEntrySize(String name) { /** * @return the manifest information for this abstract archive */ + @Override public Manifest getManifest() throws IOException { JarInputStream jis = new JarInputStream(new ByteArrayInputStream(file)); Manifest m = jis.getManifest(); @@ -288,6 +297,7 @@ public Manifest getManifest() throws IOException { * * @param name the archive name */ + @Override public boolean renameTo(String name) { return false; } diff --git a/nucleus/deployment/common/src/main/java/com/sun/enterprise/deployment/deploy/shared/OutputJarArchive.java b/nucleus/deployment/common/src/main/java/com/sun/enterprise/deployment/deploy/shared/OutputJarArchive.java index 35b600e04cf..82400808164 100644 --- a/nucleus/deployment/common/src/main/java/com/sun/enterprise/deployment/deploy/shared/OutputJarArchive.java +++ b/nucleus/deployment/common/src/main/java/com/sun/enterprise/deployment/deploy/shared/OutputJarArchive.java @@ -21,7 +21,6 @@ import java.io.File; import java.io.FileOutputStream; import java.io.IOException; -import java.io.OutputStream; import java.net.URI; import java.net.URISyntaxException; import java.util.Collection; @@ -35,6 +34,7 @@ import java.util.zip.ZipOutputStream; import org.glassfish.api.deployment.archive.WritableArchive; +import org.glassfish.api.deployment.archive.WritableArchiveEntry; import org.glassfish.hk2.api.PerLookup; import org.jvnet.hk2.annotations.Service; @@ -52,7 +52,7 @@ public class OutputJarArchive extends JarArchive implements WritableArchive { private URI uri; // the file we are currently mapped to (if open for writing) - protected ZipOutputStream jos; + private ZipOutputStream jos; private Manifest manifest; @@ -75,8 +75,6 @@ public long getArchiveSize() throws NullPointerException, SecurityException { @Override public void close() throws IOException { if (jos != null) { - jos.flush(); - jos.finish(); jos.close(); jos = null; } @@ -103,9 +101,7 @@ public void create(URI path) throws IOException { Logger.getAnonymousLogger().log(Level.WARNING, "Error in deleting file " + file.getAbsolutePath()); } } - FileOutputStream fos = new FileOutputStream(file); - BufferedOutputStream bos = new BufferedOutputStream(fos); - jos = new ZipOutputStream(bos); + jos = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(file))); } /** @@ -146,23 +142,22 @@ public URI getURI() { @Override public WritableArchive createSubArchive(String name) throws IOException { - OutputStream os = putNextEntry(name); - ZipOutputStream jos = new ZipOutputStream(os); - OutputJarArchive ja = new OutputJarArchive(); + ZipOutputStream zip = new ZipOutputStream(putNextEntry(name)); + OutputJarArchive jar = new OutputJarArchive(); try { - ja.uri = new URI("jar", name, null); - } catch(URISyntaxException e) { - + jar.uri = new URI("jar", name, null); + } catch (URISyntaxException e) { + throw new IllegalArgumentException("Could not create a subarchive for name " + name, e); } - ja.jos = jos; - return ja; + jar.jos = zip; + return jar; } /** * Close a previously returned sub archive * * @param subArchive output stream to close - * @link Archive.getSubArchive} + * @see WritableArchive#createSubArchive(String) */ @Override public void closeEntry(WritableArchive subArchive) throws IOException { @@ -180,25 +175,12 @@ public void closeEntry(WritableArchive subArchive) throws IOException { * current abstract archive. */ @Override - public OutputStream putNextEntry(String name) throws java.io.IOException { + public WritableArchiveEntry putNextEntry(String name) throws java.io.IOException { if (jos != null) { ZipEntry ze = new ZipEntry(name); jos.putNextEntry(ze); entries.add(name); } - return jos; - } - - - /** - * closes the current entry - */ - @Override - public void closeEntry() throws IOException { - if (jos != null) { - jos.flush(); - jos.closeEntry(); - } + return new WritableArchiveEntry(jos, jos); } - } diff --git a/nucleus/deployment/common/src/main/java/org/glassfish/deployment/common/ClientJarWriter.java b/nucleus/deployment/common/src/main/java/org/glassfish/deployment/common/ClientJarWriter.java index 2fc624a996d..f45b79221bb 100644 --- a/nucleus/deployment/common/src/main/java/org/glassfish/deployment/common/ClientJarWriter.java +++ b/nucleus/deployment/common/src/main/java/org/glassfish/deployment/common/ClientJarWriter.java @@ -1,4 +1,5 @@ /* + * Copyright (c) 2022 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 @@ -19,7 +20,16 @@ import com.sun.enterprise.deployment.deploy.shared.InputJarArchive; import com.sun.enterprise.deployment.deploy.shared.OutputJarArchive; import com.sun.enterprise.util.io.FileUtils; -import java.io.*; + +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; import java.net.URI; import java.net.URISyntaxException; import java.util.ArrayList; @@ -35,13 +45,14 @@ import java.util.jar.Manifest; import java.util.logging.Level; import java.util.logging.Logger; + import org.glassfish.api.deployment.DeployCommandParameters; import org.glassfish.api.deployment.OpsParams; import org.glassfish.api.deployment.archive.ReadableArchive; import org.glassfish.api.deployment.archive.WritableArchive; -import org.glassfish.internal.deployment.ExtendedDeploymentContext; +import org.glassfish.api.deployment.archive.WritableArchiveEntry; import org.glassfish.deployment.versioning.VersioningUtils; - +import org.glassfish.internal.deployment.ExtendedDeploymentContext; import org.glassfish.logging.annotation.LogMessageInfo; /** @@ -68,7 +79,7 @@ public class ClientJarWriter { private final ExtendedDeploymentContext deploymentContext; private final String name; - private Map jarFiles = new HashMap(); + private final Map jarFiles = new HashMap<>(); public ClientJarWriter(final ExtendedDeploymentContext deploymentContext) { this.deploymentContext = deploymentContext; @@ -137,7 +148,7 @@ private File createClientJARIfNeeded(final ExtendedDeploymentContext deploymentC * need to add the manifest to it if a manifst is not already in the collection. * The client artifacts manager returns an unalterable collection. */ - final Collection artifacts = new ArrayList(clientArtifactsManager.artifacts()); + final Collection artifacts = new ArrayList<>(clientArtifactsManager.artifacts()); OutputJarArchive generatedClientJAR = new OutputJarArchive(); try { @@ -233,7 +244,7 @@ private static String generatedClientJARPrefix(final String earName) { private void copyArtifactsToClientJAR( final WritableArchive generatedClientJARArchive, final Collection artifacts) throws IOException { - final Set pathsWrittenToJAR = new HashSet(); + final Set pathsWrittenToJAR = new HashSet<>(); StringBuilder copiedFiles = (deplLogger.isLoggable(Level.FINER)) ? new StringBuilder() : null; for (Artifacts.FullAndPartURIs artifact : artifacts) { /* @@ -244,53 +255,28 @@ private void copyArtifactsToClientJAR( int previousSlash = artPath.indexOf('/'); while (previousSlash != -1) { String partialAncestorPath = artPath.substring(0, previousSlash + 1); - if ( ! pathsWrittenToJAR.contains(partialAncestorPath)) { - generatedClientJARArchive.putNextEntry(partialAncestorPath); - generatedClientJARArchive.closeEntry(); + if (!pathsWrittenToJAR.contains(partialAncestorPath)) { + try (WritableArchiveEntry entry = generatedClientJARArchive.putNextEntry(partialAncestorPath)) { + // just an empty entry + } pathsWrittenToJAR.add(partialAncestorPath); } previousSlash = artPath.indexOf('/', previousSlash + 1); } - OutputStream os = generatedClientJARArchive.putNextEntry(artifact.getPart().toASCIIString()); - InputStream is = null; - try { - final URI fullURI = artifact.getFull(); - final String scheme = fullURI.getScheme(); - if (scheme.equals("file")) { - is = new BufferedInputStream(new FileInputStream(new File(artifact.getFull()))); - } else if (scheme.equals("jar")) { - final String ssp = fullURI.getSchemeSpecificPart(); - URI jarURI = new URI(ssp.substring(0, ssp.indexOf("!/"))); - JarFile jf = jarFiles.get(jarURI); - if (jf == null) { - jf = new JarFile(new File(jarURI)); - jarFiles.put(jarURI, jf); - } - final String entryName = ssp.substring(ssp.indexOf("!/") + 2); - final JarEntry jarEntry = jf.getJarEntry(entryName); - is = jf.getInputStream(jarEntry); - } else { - throw new IllegalArgumentException(scheme + " != [file,jar]"); - } + try (WritableArchiveEntry os = generatedClientJARArchive.putNextEntry(artifact.getPart().toASCIIString()); + InputStream is = openInputStream(artifact)) { DeploymentUtils.copyStream(is, os); if (copiedFiles != null) { - copiedFiles.append(LINE_SEP). - append(" "). - append(artifact.getFull().toASCIIString()). - append(" -> "). - append(artifact.getPart().toASCIIString()); + copiedFiles.append(LINE_SEP).append(" ").append(artifact.getFull().toASCIIString()).append(" -> ") + .append(artifact.getPart().toASCIIString()); } } catch (Exception ex) { deplLogger.log(Level.WARNING, EXCEPTION_CAUGHT, ex.getLocalizedMessage()); } finally { - if (is != null) { - is.close(); - } - generatedClientJARArchive.closeEntry(); if (artifact.isTemporary()) { final File artifactFile = new File(artifact.getFull()); - if ( ! artifactFile.delete()) { + if (!artifactFile.delete()) { artifactFile.deleteOnExit(); } } @@ -301,4 +287,26 @@ private void copyArtifactsToClientJAR( } } + + private InputStream openInputStream(Artifacts.FullAndPartURIs artifact) + throws FileNotFoundException, URISyntaxException, IOException { + final URI fullURI = artifact.getFull(); + final String scheme = fullURI.getScheme(); + if (scheme.equals("file")) { + return new BufferedInputStream(new FileInputStream(new File(artifact.getFull()))); + } else if (scheme.equals("jar")) { + final String ssp = fullURI.getSchemeSpecificPart(); + URI jarURI = new URI(ssp.substring(0, ssp.indexOf("!/"))); + JarFile jf = jarFiles.get(jarURI); + if (jf == null) { + jf = new JarFile(new File(jarURI)); + jarFiles.put(jarURI, jf); + } + final String entryName = ssp.substring(ssp.indexOf("!/") + 2); + final JarEntry jarEntry = jf.getJarEntry(entryName); + return jf.getInputStream(jarEntry); + } else { + throw new IllegalArgumentException(scheme + " != [file,jar]"); + } + } } diff --git a/nucleus/deployment/common/src/main/java/org/glassfish/deployment/common/DeploymentUtils.java b/nucleus/deployment/common/src/main/java/org/glassfish/deployment/common/DeploymentUtils.java index d7551e79de0..a62d2bae896 100644 --- a/nucleus/deployment/common/src/main/java/org/glassfish/deployment/common/DeploymentUtils.java +++ b/nucleus/deployment/common/src/main/java/org/glassfish/deployment/common/DeploymentUtils.java @@ -24,7 +24,6 @@ import static java.util.jar.JarFile.MANIFEST_NAME; import static java.util.logging.Level.WARNING; -import java.io.BufferedInputStream; import java.io.File; import java.io.IOException; import java.io.InputStream; @@ -48,6 +47,7 @@ import org.glassfish.api.deployment.archive.ArchiveType; import org.glassfish.api.deployment.archive.ReadableArchive; import org.glassfish.api.deployment.archive.WritableArchive; +import org.glassfish.api.deployment.archive.WritableArchiveEntry; import org.glassfish.hk2.api.ServiceLocator; import org.glassfish.loader.util.ASClassLoaderUtil; import org.glassfish.logging.annotation.LogMessageInfo; @@ -110,7 +110,7 @@ public static long checksum(final File directory) { throw new IllegalArgumentException(msg); } - final List uris = new ArrayList(); + final List uris = new ArrayList<>(); scanDirectory(directory.toURI(), directory, uris); /* @@ -310,24 +310,18 @@ public static void expand(ReadableArchive source, WritableArchive target) throws Enumeration e = source.entries(); while (e.hasMoreElements()) { String entryName = e.nextElement(); - InputStream is = new BufferedInputStream(source.getEntry(entryName)); - OutputStream os = null; - try { - os = target.putNextEntry(entryName); - FileUtils.copy(is, os, source.getEntrySize(entryName)); - } finally { - if (os != null) { - target.closeEntry(); - } - is.close(); + try (InputStream is = source.getEntry(entryName); + WritableArchiveEntry os = target.putNextEntry(entryName)) { + FileUtils.copy(is, os); } } // Last is manifest if exists Manifest manifest = source.getManifest(); if (manifest != null) { - manifest.write(target.putNextEntry(MANIFEST_NAME)); - target.closeEntry(); + try (OutputStream entry = target.putNextEntry(MANIFEST_NAME)) { + manifest.write(entry); + } } } @@ -384,7 +378,7 @@ private static List getManifestLibraries(ReadableArchive archive, Manifest } public static List getExternalLibraries(ReadableArchive archive) { - List externalLibURIs = new ArrayList(); + List externalLibURIs = new ArrayList<>(); try { List manifestURLs = getManifestLibraries(archive); URI archiveURI = archive.getURI(); diff --git a/nucleus/deployment/common/src/main/java/org/glassfish/deployment/common/ModuleExploder.java b/nucleus/deployment/common/src/main/java/org/glassfish/deployment/common/ModuleExploder.java index a80c3f51e55..4d1a507a337 100644 --- a/nucleus/deployment/common/src/main/java/org/glassfish/deployment/common/ModuleExploder.java +++ b/nucleus/deployment/common/src/main/java/org/glassfish/deployment/common/ModuleExploder.java @@ -75,9 +75,9 @@ public static void explodeJar(File source, File destination) throws IOException if (!out.getParentFile().exists()) { out.getParentFile().mkdirs(); } - InputStream is = new BufferedInputStream(jarFile.getInputStream(entry)); - FileOutputStream fos = FileUtils.openFileOutputStream(out); - FileUtils.copy(is, fos, entry.getSize()); + try (InputStream is = jarFile.getInputStream(entry)) { + FileUtils.copy(is, out, entry.getSize()); + } } } } catch(Throwable e) { diff --git a/nucleus/deployment/common/src/test/java/com/sun/enterprise/deploy/shared/FileArchiveTest.java b/nucleus/deployment/common/src/test/java/com/sun/enterprise/deploy/shared/FileArchiveTest.java index 48276f77b59..56b18d5e1a7 100644 --- a/nucleus/deployment/common/src/test/java/com/sun/enterprise/deploy/shared/FileArchiveTest.java +++ b/nucleus/deployment/common/src/test/java/com/sun/enterprise/deploy/shared/FileArchiveTest.java @@ -36,6 +36,7 @@ import org.glassfish.api.deployment.archive.ReadableArchive; import org.glassfish.api.deployment.archive.WritableArchive; +import org.glassfish.api.deployment.archive.WritableArchiveEntry; import org.glassfish.hk2.api.ServiceLocator; import org.glassfish.main.jul.handler.LogCollectorHandler; import org.glassfish.main.jul.record.GlassFishLogRecord; @@ -165,29 +166,28 @@ private void clean(final File dir) { private ReadableArchive createAndPopulateArchive(final Set entryNames) throws Exception { - WritableArchive instance = archiveFactory.createArchive(archiveDir.toURI()); - instance.create(archiveDir.toURI()); - - // Add some entries. - for (String entryName : entryNames) { - instance.putNextEntry(entryName); - instance.closeEntry(); + try (WritableArchive instance = archiveFactory.createArchive(archiveDir.toURI())) { + instance.create(archiveDir.toURI()); + // Add some entries. + for (String entryName : entryNames) { + try (WritableArchiveEntry entry = instance.putNextEntry(entryName)) { + // just an empty entry + } + } } - instance.close(); return archiveFactory.openArchive(archiveDir); } - private ReadableArchive createAndPopulateSubarchive( - final WritableArchive parent, - final String subarchiveName, - final Set entryNames) throws Exception { - final WritableArchive result = parent.createSubArchive(subarchiveName); - for (String entryName : entryNames) { - result.putNextEntry(entryName); - result.closeEntry(); - } - result.close(); + private ReadableArchive createAndPopulateSubarchive(final WritableArchive parent, final String subarchiveName, + final Set entryNames) throws Exception { + try (WritableArchive result = parent.createSubArchive(subarchiveName)) { + for (String entryName : entryNames) { + try (WritableArchiveEntry entry = result.putNextEntry(entryName)) { + // just an empty entry + } + } + } final ReadableArchive readableParent = archiveFactory.openArchive(parent.getURI()); return readableParent.getSubArchive(subarchiveName); } diff --git a/nucleus/osgi-platforms/osgi-container/src/main/java/org/glassfish/extras/osgicontainer/OSGiArchiveHandler.java b/nucleus/osgi-platforms/osgi-container/src/main/java/org/glassfish/extras/osgicontainer/OSGiArchiveHandler.java index 403c982b6fe..e10c1acee50 100644 --- a/nucleus/osgi-platforms/osgi-container/src/main/java/org/glassfish/extras/osgicontainer/OSGiArchiveHandler.java +++ b/nucleus/osgi-platforms/osgi-container/src/main/java/org/glassfish/extras/osgicontainer/OSGiArchiveHandler.java @@ -1,4 +1,5 @@ /* + * Copyright (c) 2022 Contributors to the Eclipse Foundation * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the @@ -17,27 +18,36 @@ package org.glassfish.extras.osgicontainer; import com.sun.enterprise.util.io.FileUtils; -import org.glassfish.api.deployment.DeployCommandParameters; -import org.glassfish.api.deployment.DeploymentContext; -import org.glassfish.api.deployment.archive.CompositeHandler; -import org.glassfish.api.deployment.archive.ReadableArchive; -import org.glassfish.api.deployment.archive.WritableArchive; -import org.glassfish.internal.deployment.GenericHandler; -import org.jvnet.hk2.annotations.Service; import jakarta.inject.Inject; import jakarta.inject.Singleton; -import java.io.*; -import java.net.*; + +import java.io.IOException; +import java.io.OutputStream; +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; import java.util.Enumeration; import java.util.Properties; -import java.util.jar.*; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; +import java.util.jar.JarInputStream; +import java.util.jar.Manifest; import java.util.logging.Level; import java.util.logging.Logger; +import org.glassfish.api.deployment.DeployCommandParameters; +import org.glassfish.api.deployment.DeploymentContext; +import org.glassfish.api.deployment.archive.CompositeHandler; +import org.glassfish.api.deployment.archive.ReadableArchive; +import org.glassfish.api.deployment.archive.WritableArchive; +import org.glassfish.api.deployment.archive.WritableArchiveEntry; +import org.glassfish.internal.deployment.GenericHandler; import org.glassfish.logging.annotation.LogMessageInfo; import org.glassfish.logging.annotation.LogMessagesResourceBundle; import org.glassfish.logging.annotation.LoggerInfo; +import org.jvnet.hk2.annotations.Service; /** * Archive Handler for OSGi modules. @@ -71,33 +81,39 @@ public class OSGiArchiveHandler extends GenericHandler implements CompositeHandl @Inject private OSGiArchiveDetector detector; - private String URI_SCHEME_PROP_NAME = "UriScheme"; - private char QUERY_PARAM_SEP = '&'; - private String QUERY_DELIM = "?"; - private String SCHEME_SEP = ":"; + private final String URI_SCHEME_PROP_NAME = "UriScheme"; + private final char QUERY_PARAM_SEP = '&'; + private final String QUERY_DELIM = "?"; + private final String SCHEME_SEP = ":"; + @Override public String getArchiveType() { return OSGiArchiveDetector.OSGI_ARCHIVE_TYPE; } + @Override public boolean accept(ReadableArchive source, String entryName) { // we hide everything so far. return false; } + @Override public void initCompositeMetaData(DeploymentContext context) { // nothing to initialize } + @Override public boolean handles(ReadableArchive archive) throws IOException { return detector.handles(archive); } + @Override public ClassLoader getClassLoader(ClassLoader parent, DeploymentContext context) { return parent; } + @Override public String getDefaultApplicationName(ReadableArchive archive, DeploymentContext context) { return getDefaultApplicationNameFromArchiveName(archive); @@ -114,17 +130,16 @@ public String getDefaultApplicationName(ReadableArchive archive, * @throws IOException when the archive is corrupted */ @Override - public void expand(ReadableArchive source, WritableArchive target, - DeploymentContext context) throws IOException { - Properties props = context - .getCommandParameters(DeployCommandParameters.class).properties; + public void expand(ReadableArchive source, WritableArchive target, DeploymentContext context) throws IOException { + Properties props = context.getCommandParameters(DeployCommandParameters.class).properties; if ((props != null) && (props.containsKey(URI_SCHEME_PROP_NAME))) { // if UriScheme is specified, we need to construct a new URL based on user's input // and souce parameter and call openConnection() and getInputStream() on it. URL url = prepareUrl(context, props); - logger.log(Level.INFO, DECORATED_URL, new Object[]{url}); - final JarInputStream jis = new JarInputStream(url.openStream()); - expandJar(jis, target); + logger.log(Level.INFO, DECORATED_URL, url); + try (JarInputStream jis = new JarInputStream(url.openStream())) { + expandJar(jis, target); + } } else { super.expand(source, target, context); } @@ -188,54 +203,40 @@ private URL prepareUrl(DeploymentContext context, Properties props) /** * Populates a writable archive by reading the input JarInputStream. - * It closes both the input and output at the end. + * * @param jis * @param target * @throws IOException */ private void expandJar(JarInputStream jis, WritableArchive target) throws IOException { - try { - JarEntry je; - while ((je = jis.getNextJarEntry()) != null) { - OutputStream os = null; - try { - if (je.isDirectory()) { - logger.logp(Level.FINER, "OSGiArchiveHandler", "expandJar", - "Skipping jar entry = {0} since this is of directiry type", new Object[]{je}); - continue; - } - final String entryName = je.getName(); - final long entrySize = je.getSize(); - logger.logp(Level.FINER, "OSGiArchiveHandler", "expandJar", "Writing jar entry name = {0}, size = {1}", - new Object[]{entryName, entrySize}); - os = target.putNextEntry(entryName); - FileUtils.copy(jis, os, entrySize < 0 ? 0 : entrySize); // passing 0 will force it to read until EOS - } finally { - if (os != null) { - target.closeEntry(); - } - jis.closeEntry(); + JarEntry je; + while ((je = jis.getNextJarEntry()) != null) { + try { + if (je.isDirectory()) { + logger.logp(Level.FINER, "OSGiArchiveHandler", "expandJar", + "Skipping jar entry = {0} since this is of directiry type", new Object[] {je}); + continue; + } + final String entryName = je.getName(); + final long entrySize = je.getSize(); + logger.logp(Level.FINER, "OSGiArchiveHandler", "expandJar", "Writing jar entry name = {0}, size = {1}", + new Object[] {entryName, entrySize}); + try (WritableArchiveEntry os = target.putNextEntry(entryName)) { + // passing 0 will force it to read until EOS + FileUtils.copy(jis, os); } + } finally { + jis.closeEntry(); } + } - //Add MANIFEST File To Target and Write the MANIFEST File To Target - Manifest m = jis.getManifest(); - if (m != null) { - logger.logp(Level.FINER, "OSGiArchiveHandler", "expandJar", "Writing manifest entry"); - OutputStream os = null; - try { - os = target.putNextEntry(JarFile.MANIFEST_NAME); - m.write(os); - } finally { - if (os != null) { - target.closeEntry(); - } - } + // Add MANIFEST File To Target and Write the MANIFEST File To Target + Manifest m = jis.getManifest(); + if (m != null) { + logger.logp(Level.FINER, "OSGiArchiveHandler", "expandJar", "Writing manifest entry"); + try (OutputStream os = target.putNextEntry(JarFile.MANIFEST_NAME)) { + m.write(os); } - } finally { - if (jis != null) - jis.close(); - target.close(); } } @@ -245,6 +246,7 @@ private void expandJar(JarInputStream jis, WritableArchive target) throws IOExce * @param archive file * @return whether this archive requires annotation scanning */ + @Override public boolean requiresAnnotationScanning(ReadableArchive archive) { return false; } diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/common/Util.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/common/Util.java index 61323f2a28e..4e29cddda87 100644 --- a/nucleus/security/core/src/main/java/com/sun/enterprise/security/common/Util.java +++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/common/Util.java @@ -1,4 +1,5 @@ /* + * Copyright (c) 2022 Contributors to the Eclipse Foundation * Copyright (c) 1997, 2020 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the @@ -16,10 +17,16 @@ package com.sun.enterprise.security.common; +import com.sun.enterprise.util.io.FileUtils; + +import jakarta.inject.Inject; +import jakarta.inject.Singleton; + import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; +import java.nio.file.Path; import java.util.List; import javax.security.auth.callback.CallbackHandler; @@ -31,11 +38,7 @@ import org.glassfish.internal.embedded.Server; import org.jvnet.hk2.annotations.Service; -import jakarta.inject.Inject; -import jakarta.inject.Singleton; - /** - * * @author venu TODO: need to change this class, it needs to be similar to SecurityServicesUtil */ @Service @@ -116,45 +119,27 @@ public static File writeConfigFileToTempDir(String fileName) throws IOException } } else { - /* - * File parent directory does not exist - so create parent directory as user.home/.glassfish-{embedded}/config - */ - String userHome = System.getProperty("user.home"); - String embeddedServerName = getCurrentEmbeddedServerName(); - File tempDir = new File(userHome + File.separator + ".glassfish7-" + embeddedServerName + File.separator + "config"); + File tempDir = FileUtils.USER_HOME.toPath().resolve(Path.of(".glassfish7-" + embeddedServerName, "config")) + .toFile(); boolean mkDirSuccess = true; if (!tempDir.exists()) { mkDirSuccess = tempDir.mkdirs(); + tempDir.deleteOnExit(); } - - localFile = new File(tempDir.getAbsolutePath() + File.separator + fileName); - + localFile = new File(tempDir, fileName); if (mkDirSuccess && !localFile.exists()) { localFile.createNewFile(); + localFile.deleteOnExit(); } } - FileOutputStream oStream = null; - InputStream iStream = null; - try { - oStream = new FileOutputStream(localFile); - iStream = Util.class.getResourceAsStream("/config/" + fileName); - + try (FileOutputStream oStream = new FileOutputStream(localFile); + InputStream iStream = Util.class.getResourceAsStream("/config/" + fileName)) { while (iStream != null && iStream.available() > 0) { oStream.write(iStream.read()); } - } finally { - if (oStream != null) { - oStream.close(); - } - if (iStream != null) { - iStream.close(); - } - } - return localFile; - } public static String getCurrentEmbeddedServerName() { diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/embedded/EmbeddedSecurityUtil.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/embedded/EmbeddedSecurityUtil.java index 8ec6d326741..dffb35827d9 100644 --- a/nucleus/security/core/src/main/java/com/sun/enterprise/security/embedded/EmbeddedSecurityUtil.java +++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/embedded/EmbeddedSecurityUtil.java @@ -22,7 +22,6 @@ import com.sun.enterprise.security.EmbeddedSecurity; import com.sun.enterprise.security.SecurityLoggerInfo; import com.sun.enterprise.util.StringUtils; -import com.sun.enterprise.util.io.FileUtils; import jakarta.inject.Singleton; @@ -30,6 +29,7 @@ import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; +import java.nio.file.Files; import java.util.ArrayList; import java.util.List; import java.util.logging.Level; @@ -52,7 +52,6 @@ * * @author Nithya Subramanian */ - @Service @Singleton public class EmbeddedSecurityUtil implements EmbeddedSecurity { @@ -111,7 +110,7 @@ public void copyConfigFiles(ServiceLocator habitat, File fromInstanceDir, File d //Copy files into new directory for (String fileName : fileNames) { - FileUtils.copyFile(new File(fileName), new File(toConfigDir, parseFileName(fileName))); + Files.copy(new File(fileName).toPath(), new File(toConfigDir, parseFileName(fileName)).toPath()); } } catch (IOException e) { _logger.log(Level.WARNING, SecurityLoggerInfo.ioError, e); From d9f45344ce9955527a1e8b17e803ce4e2976a3b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Mat=C4=9Bj=C4=8Dek?= Date: Tue, 20 Feb 2024 18:09:23 +0100 Subject: [PATCH 02/12] Fixed JAR/ZIP file management, entries MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Safer impl without resource leaks (I hope, there's yet one class with really wide scope and also some finalizers, should be revisited later again). - More logs - it is hard to find what is wrong when it just does something in the background. - I wanted to write some tests around DeploymentContext, but it has too many dependencies, so it is covered just by integration tests (persistence_all ie) Signed-off-by: David Matějček # Conflicts: # appserver/tests/testcontainers/src/test/java/org/glassfish/main/test/tc/GlassFishContainer.java --- .../client/acc/MainClassLaunchable.java | 52 +---- .../server/core/AppClientDeployerHelper.java | 39 ++-- .../core/AppClientGroupFacadeGenerator.java | 80 +++----- .../StandaloneAppClientDeployerHelper.java | 15 +- .../archivist/ApplicationArchivist.java | 20 +- .../deployment/archivist/Archivist.java | 9 +- .../archivist/DescriptorArchivist.java | 4 +- .../archivist/ExtensionsArchivist.java | 6 +- .../javaee/full/deployment/EarDeployer.java | 33 ++-- .../javaee/full/deployment/EarHandler.java | 4 +- .../persistence/jpa/JPADeployer.java | 3 +- .../com/sun/enterprise/util/io/FileUtils.java | 18 +- .../admin/payload/PayloadFilesManager.java | 172 ++++------------- .../sun/enterprise/util/io/FileUtilsTest.java | 76 ++++++-- .../api/deployment/archive/Archive.java | 2 +- .../deployment/archive/WritableArchive.java | 8 - .../archive/WritableArchiveEntry.java | 50 ++--- .../enterprise/v3/server/UpgradeStartup.java | 2 +- .../deployment/admin/DeployCommand.java | 108 ++++++----- .../deployment/admin/UndeployCommand.java | 78 ++++---- .../shared/AbstractReadableArchive.java | 23 ++- .../deploy/shared/ArchiveFactory.java | 1 - .../enterprise/deploy/shared/FileArchive.java | 60 +++--- .../deploy/shared/InputJarArchive.java | 30 ++- .../deployment/deploy/shared/JarArchive.java | 11 +- .../deploy/shared/MemoryMappedArchive.java | 110 ++++++----- .../deploy/shared/OutputJarArchive.java | 82 ++++---- .../deployment/common/Artifacts.java | 178 ++++++++---------- .../common/ClientArtifactsManager.java | 114 +++++------ .../deployment/common/ClientJarWriter.java | 176 +++++++---------- .../common/DeploymentContextImpl.java | 68 ++++--- .../deployment/common/DeploymentUtils.java | 16 +- .../versioning/VersioningService.java | 53 +++--- .../versioning/VersioningUtils.java | 44 ++--- .../deploy/shared/InputJarArchiveTest.java | 10 +- .../osgicontainer/OSGiArchiveHandler.java | 1 - 36 files changed, 779 insertions(+), 977 deletions(-) diff --git a/appserver/appclient/client/acc/src/main/java/org/glassfish/appclient/client/acc/MainClassLaunchable.java b/appserver/appclient/client/acc/src/main/java/org/glassfish/appclient/client/acc/MainClassLaunchable.java index 73c67743570..36ba88c7494 100644 --- a/appserver/appclient/client/acc/src/main/java/org/glassfish/appclient/client/acc/MainClassLaunchable.java +++ b/appserver/appclient/client/acc/src/main/java/org/glassfish/appclient/client/acc/MainClassLaunchable.java @@ -27,6 +27,8 @@ import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; +import java.lang.System.Logger; +import java.lang.System.Logger.Level; import java.net.URI; import java.net.URLClassLoader; import java.security.AccessController; @@ -48,14 +50,14 @@ * @author tjquinn */ public class MainClassLaunchable implements Launchable { + private static final Logger LOG = System.getLogger(MainClassLaunchable.class.getName()); private final Class mainClass; private ApplicationClientDescriptor acDesc; private ClassLoader classLoader; private AppClientArchivist archivist; - MainClassLaunchable(final ServiceLocator habitat, final Class mainClass) { - super(); + MainClassLaunchable(final ServiceLocator habitat, final Class mainClass) { this.mainClass = mainClass; } @@ -66,20 +68,11 @@ public Class getMainClass() throws ClassNotFoundException { @Override public ApplicationClientDescriptor getDescriptor(final URLClassLoader loader) throws IOException, SAXException { - /* - * There is no developer-provided descriptor possible so just - * use a default one. - */ + // There is no developer-provided descriptor possible so just use a default one. if (acDesc == null) { ReadableArchive tempArchive = null; - final ACCClassLoader tempLoader = AccessController.doPrivileged( - new PrivilegedAction() { - - @Override - public ACCClassLoader run() { - return new ACCClassLoader(loader.getURLs(), loader.getParent()); - } - }); + PrivilegedAction action = () -> new ACCClassLoader(loader.getURLs(), loader.getParent()); + final ACCClassLoader tempLoader = AccessController.doPrivileged(action); tempArchive = createArchive(tempLoader, mainClass); final AppClientArchivist acArchivist = getArchivist(tempArchive, tempLoader); archivist.setClassLoader(tempLoader); @@ -97,34 +90,9 @@ private String appNameFromMainClass(final Class c) { return c.getName(); } -// private ReadableArchive createArchive(final ClassLoader loader, -// final Class mainClass) throws IOException, URISyntaxException { -// Manifest mf = new Manifest(); -// mf.getMainAttributes().put(Attributes.Name.MAIN_CLASS, mainClass.getName()); -// final File tempFile = File.createTempFile("acc", ".jar"); -// tempFile.deleteOnExit(); -// JarOutputStream jos = new JarOutputStream( -// new BufferedOutputStream(new FileOutputStream(tempFile)), mf); -// final String mainClassResourceName = mainClass.getName().replace('.', '/') + ".class"; -// final ZipEntry mainClassEntry = new ZipEntry(mainClassResourceName); -// jos.putNextEntry(mainClassEntry); -// InputStream is = loader.getResourceAsStream(mainClassResourceName); -// int bytesRead; -// byte[] buffer = new byte[1024]; -// while ( (bytesRead = is.read(buffer)) != -1) { -// jos.write(buffer, 0, bytesRead); -// } -// is.close(); -// jos.closeEntry(); -// jos.close(); -// -// final InputJarArchive result = new InputJarArchive(); -// result.open(new URI("jar", tempFile.toURI().toASCIIString(), null)); -// return result; -// } - - private ReadableArchive createArchive(final ClassLoader loader, - final Class mainClass) throws IOException { + + private ReadableArchive createArchive(final ClassLoader loader, final Class mainClass) throws IOException { + LOG.log(Level.DEBUG, "createArchive(loader, mainClass={0})", mainClass); ByteArrayOutputStream baos = new ByteArrayOutputStream(); Manifest mf = new Manifest(); diff --git a/appserver/appclient/server/core/src/main/java/org/glassfish/appclient/server/core/AppClientDeployerHelper.java b/appserver/appclient/server/core/src/main/java/org/glassfish/appclient/server/core/AppClientDeployerHelper.java index 7791227997a..ba980a5780e 100644 --- a/appserver/appclient/server/core/src/main/java/org/glassfish/appclient/server/core/AppClientDeployerHelper.java +++ b/appserver/appclient/server/core/src/main/java/org/glassfish/appclient/server/core/AppClientDeployerHelper.java @@ -27,7 +27,6 @@ import java.io.File; import java.io.IOException; import java.io.InputStream; -import java.io.OutputStream; import java.net.URI; import java.net.URISyntaxException; import java.text.MessageFormat; @@ -56,7 +55,6 @@ import org.glassfish.appclient.server.core.jws.servedcontent.StaticContent; import org.glassfish.appclient.server.core.jws.servedcontent.TokenHelper; import org.glassfish.deployment.common.Artifacts; -import org.glassfish.deployment.common.DeploymentUtils; import org.glassfish.deployment.versioning.VersioningSyntaxException; import org.glassfish.deployment.versioning.VersioningUtils; import org.glassfish.hk2.api.ServiceLocator; @@ -339,21 +337,20 @@ public String clientName() { * if the classPathElement is for a submodule; null otherwise */ File JAROfExpandedSubmodule(final URI candidateSubmoduleURI) throws IOException { - ReadableArchive source = new FileArchive(); - source.open(dc().getSource().getParentArchive().getURI().resolve(expandedDirURI(candidateSubmoduleURI))); - OutputJarArchive target = new OutputJarArchive(); - target.create(dc().getScratchDir("xml").toURI().resolve(candidateSubmoduleURI)); - /* - * Copy the manifest explicitly because the ReadableArchive - * entries() method omits it. - */ - Manifest mf = source.getManifest(); - try (OutputStream os = target.putNextEntry(JarFile.MANIFEST_NAME)) { - mf.write(os); + URI uri = dc().getSource().getParentArchive().getURI().resolve(expandedDirURI(candidateSubmoduleURI)); + try (FileArchive source = new FileArchive(uri); OutputJarArchive target = new OutputJarArchive()) { + target.create(dc().getScratchDir("xml").toURI().resolve(candidateSubmoduleURI)); + /* + * Copy the manifest explicitly because the ReadableArchive + * entries() method omits it. + */ + Manifest mf = source.getManifest(); + try (WritableArchiveEntry os = target.putNextEntry(JarFile.MANIFEST_NAME)) { + mf.write(os); + } + copyArchive(source, target, Collections.emptySet()); + return new File(target.getURI()); } - copyArchive(source, target, Collections.emptySet()); - target.close(); - return new File(target.getURI()); } private URI expandedDirURI(final URI submoduleURI) { @@ -527,7 +524,7 @@ protected final void generateAppClientFacade() throws IOException, URISyntaxExce /* * Write the manifest to the facade. */ - try (OutputStream os = facadeArchive.putNextEntry(JarFile.MANIFEST_NAME)) { + try (WritableArchiveEntry os = facadeArchive.putNextEntry(JarFile.MANIFEST_NAME)) { facadeManifest.write(os); } /* @@ -595,8 +592,8 @@ static void copyArchive(ReadableArchive source, WritableArchive target, Set> it = appClients.iterator(); it.hasNext(); ) { - ModuleDescriptor md = it.next(); + for (ModuleDescriptor md : appClients) { appClientGroupListSB.append((appClientGroupListSB.length() > 0) ? " " : "") .append(earDirUserURIText(dc)).append(appClientFacadeUserURI(md.getArchiveUri())); } @@ -190,15 +194,11 @@ private void generateAndRecordEARFacadeContents( //Now manifest is ready to be written. final File manifestFile = File.createTempFile("groupMF", ".MF"); - final OutputStream manifestOutputStream = new BufferedOutputStream(new FileOutputStream(manifestFile)); //facadeArchive.putNextEntry(JarFile.MANIFEST_NAME); - try { - manifest.write(manifestOutputStream); - } finally { - manifestOutputStream.close(); + try (OutputStream manifestOutputStream = new BufferedOutputStream(new FileOutputStream(manifestFile))) { + manifest.write(manifestOutputStream); } clientArtifactsManager.add(manifestFile, JarFile.MANIFEST_NAME, true /* isTemp */); - writeMainClass(clientArtifactsManager); /* @@ -228,39 +228,19 @@ private File getPermissionsFile() { } private void writeMainClass(final ClientArtifactsManager clientArtifactsManager) throws IOException { - final String mainClassResourceName = - GLASSFISH_APPCLIENT_GROUP_FACADE_CLASS_NAME.replace('.', '/') + - ".class"; - final File mainClassJAR = new File( - AppClientDeployerHelper.getModulesDir(serviceLocator), - AppClientDeployerHelper.GF_CLIENT_MODULE_PATH); + final String mainClassResourceName = GLASSFISH_APPCLIENT_GROUP_FACADE_CLASS_NAME.replace('.', '/') + ".class"; + final File mainClassJAR = new File(AppClientDeployerHelper.getModulesDir(serviceLocator), + AppClientDeployerHelper.GF_CLIENT_MODULE_PATH); final File mainClassFile = File.createTempFile("main", ".class"); - final OutputStream os = new BufferedOutputStream(new FileOutputStream(mainClassFile)); - InputStream is = null; - JarFile jf = null; - try { - jf = new JarFile(mainClassJAR); - final JarEntry entry = jf.getJarEntry(mainClassResourceName); - is = jf.getInputStream(entry); - DeploymentUtils.copyStream(is, os); - is.close(); - clientArtifactsManager.add(mainClassFile, mainClassResourceName, true); - } catch (Exception e) { - throw new DeploymentException(e); - } finally { - try { - os.close(); - } finally { - try { - if (is != null) { - is.close(); - } - } finally { - if (jf != null) { - jf.close(); - } - } + try (OutputStream os = new FileOutputStream(mainClassFile); + JarFile jf = new JarFile(mainClassJAR)) { + JarEntry entry = jf.getJarEntry(mainClassResourceName); + try (InputStream is = jf.getInputStream(entry)) { + FileUtils.copy(is, os); + } catch (Exception e) { + throw new DeploymentException(e); } } + clientArtifactsManager.add(mainClassFile, mainClassResourceName, true); } } diff --git a/appserver/appclient/server/core/src/main/java/org/glassfish/appclient/server/core/StandaloneAppClientDeployerHelper.java b/appserver/appclient/server/core/src/main/java/org/glassfish/appclient/server/core/StandaloneAppClientDeployerHelper.java index a2a8940bac4..2e7d0f4e098 100644 --- a/appserver/appclient/server/core/src/main/java/org/glassfish/appclient/server/core/StandaloneAppClientDeployerHelper.java +++ b/appserver/appclient/server/core/src/main/java/org/glassfish/appclient/server/core/StandaloneAppClientDeployerHelper.java @@ -21,8 +21,8 @@ import com.sun.enterprise.deployment.ApplicationClientDescriptor; import com.sun.enterprise.deployment.archivist.AppClientArchivist; import com.sun.enterprise.deployment.deploy.shared.OutputJarArchive; +import com.sun.enterprise.util.io.FileUtils; -import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; @@ -42,6 +42,7 @@ import org.glassfish.api.deployment.DeployCommandParameters; import org.glassfish.api.deployment.DeploymentContext; import org.glassfish.api.deployment.archive.ReadableArchive; +import org.glassfish.api.deployment.archive.WritableArchiveEntry; import org.glassfish.appclient.server.core.jws.JavaWebStartInfo; import org.glassfish.appclient.server.core.jws.servedcontent.DynamicContent; import org.glassfish.appclient.server.core.jws.servedcontent.FixedContent; @@ -139,13 +140,9 @@ protected void copyFileToTopLevelJAR(final OutputJarArchive clientFacadeArchive, } private void copyToArchive(final File inputFile, final OutputJarArchive outputArchive, final String pathInJar) throws IOException { - try (OutputStream os = outputArchive.putNextEntry(pathInJar); - InputStream is = new BufferedInputStream(new FileInputStream(inputFile))) { - final byte[] buffer = new byte[512]; - int bytesRead; - while ((bytesRead = is.read(buffer)) != -1) { - os.write(buffer, 0, bytesRead); - } + try (WritableArchiveEntry os = outputArchive.putNextEntry(pathInJar); + InputStream is = new FileInputStream(inputFile)) { + FileUtils.copy(is, os); } } @@ -343,7 +340,7 @@ protected void copyOriginalAppClientJAR(final DeploymentContext dc) throws IOExc try (OutputStream os = target.putNextEntry(JarFile.MANIFEST_NAME)) { originalManifest.write(os); } - copyArchive(originalSource, target, Collections.EMPTY_SET); + copyArchive(originalSource, target, Collections.emptySet()); } } } diff --git a/appserver/deployment/dol/src/main/java/com/sun/enterprise/deployment/archivist/ApplicationArchivist.java b/appserver/deployment/dol/src/main/java/com/sun/enterprise/deployment/archivist/ApplicationArchivist.java index 511eebe9f74..148c9a3f9f6 100644 --- a/appserver/deployment/dol/src/main/java/com/sun/enterprise/deployment/archivist/ApplicationArchivist.java +++ b/appserver/deployment/dol/src/main/java/com/sun/enterprise/deployment/archivist/ApplicationArchivist.java @@ -104,9 +104,7 @@ public ArchiveType getModuleType() { protected void writeContents(ReadableArchive in, WritableArchive out) throws IOException { Set filesToSkip = new HashSet<>(); - if (DOLUtils.getDefaultLogger().isLoggable(Level.FINE)) { - DOLUtils.getDefaultLogger().fine("Write " + out.getURI() + " with " + this); - } + logger.log(Level.FINE, "writeContents(in={0}, out={1})", new Object[] {in, out}); // any files already written to the output should never be rewritten for (Enumeration alreadyWritten = out.entries(); alreadyWritten.hasMoreElements();) { @@ -120,17 +118,13 @@ protected void writeContents(ReadableArchive in, WritableArchive out) throws IOE subArchivist.initializeContext(this); subArchivist.setModuleDescriptor(aModule); String archiveUri = aModule.getArchiveUri(); - if (DOLUtils.getDefaultLogger().isLoggable(Level.FINE)) { - DOLUtils.getDefaultLogger().fine("Write " + archiveUri + " with " + subArchivist); - } - - // Create a new jar file inside the application .ear - final WritableArchive internalJar = out.createSubArchive(archiveUri); + logger.log(Level.FINE, "Writing {0} with {1}", new Object[] {archiveUri, subArchivist}); // we need to copy the old archive to a temp file so // the save method can copy its original contents from File tmpFile = null; - try (InputStream is = in.getEntry(archiveUri)) { + try (InputStream is = in.getEntry(archiveUri); + WritableArchive internalJar = out.createSubArchive(archiveUri)) { if (in instanceof WritableArchive) { subArchivist.setArchiveUri(internalJar.getURI().getSchemeSpecificPart()); } else { @@ -142,7 +136,6 @@ protected void writeContents(ReadableArchive in, WritableArchive out) throws IOE } subArchivist.writeContents(internalJar); } finally { - out.closeEntry(internalJar); if (tmpFile != null) { boolean ok = tmpFile.delete(); if (!ok) { @@ -770,13 +763,12 @@ public void copyInto(Application a, ReadableArchive source, WritableArchive targ Set entriesToSkip = new HashSet<>(); for (ModuleDescriptor aModule : a.getModules()) { entriesToSkip.add(aModule.getArchiveUri()); - try (ReadableArchive subSource = source.getSubArchive(aModule.getArchiveUri())) { - WritableArchive subTarget = target.createSubArchive(aModule.getArchiveUri()); + try (ReadableArchive subSource = source.getSubArchive(aModule.getArchiveUri()); + WritableArchive subTarget = target.createSubArchive(aModule.getArchiveUri())) { Archivist newArchivist = archivistFactory.get().getArchivist(aModule.getModuleType()); try (ReadableArchive subArchive = archiveFactory.openArchive(subTarget.getURI())) { subSource.setParentArchive(subArchive); newArchivist.copyInto(subSource, subTarget, overwriteManifest); - target.closeEntry(subTarget); String subModulePath = subSource.getURI().getSchemeSpecificPart(); String parentPath = source.getURI().getSchemeSpecificPart(); if (subModulePath.startsWith(parentPath)) { diff --git a/appserver/deployment/dol/src/main/java/com/sun/enterprise/deployment/archivist/Archivist.java b/appserver/deployment/dol/src/main/java/com/sun/enterprise/deployment/archivist/Archivist.java index 806b8d1a8c7..a616c517fce 100644 --- a/appserver/deployment/dol/src/main/java/com/sun/enterprise/deployment/archivist/Archivist.java +++ b/appserver/deployment/dol/src/main/java/com/sun/enterprise/deployment/archivist/Archivist.java @@ -239,8 +239,7 @@ public T getDescriptor() { * @param archive the archive file path * @return the deployment descriptor for this archive */ - public T open(ReadableArchive archive) - throws IOException, SAXException { + public T open(ReadableArchive archive) throws IOException, SAXException { return open(archive, (Application) null); } @@ -269,6 +268,8 @@ public T open(final ReadableArchive descriptorArchive, final ReadableArchive contentArchive, final Application app) throws IOException, SAXException { + logger.log(Level.FINE, "open(descriptorArchive={0}, contentArchive={1}, app={2})", + new Object[] {descriptorArchive, contentArchive, app}); setManifest(contentArchive.getManifest()); T descriptor = readDeploymentDescriptors(descriptorArchive, contentArchive, app); @@ -862,7 +863,7 @@ public void writeDeploymentDescriptors(ReadableArchive in, WritableArchive out) public void writeStandardDeploymentDescriptors(WritableArchive out) throws IOException { getStandardDDFile().setArchiveType(getModuleType()); - try (OutputStream os = out.putNextEntry(getDeploymentDescriptorPath())) { + try (WritableArchiveEntry os = out.putNextEntry(getDeploymentDescriptorPath())) { standardDD.write(getDescriptor(), os); } } @@ -889,7 +890,7 @@ public void writeRuntimeDeploymentDescriptors(ReadableArchive in, WritableArchiv } for (ConfigurationDeploymentDescriptorFile ddFile : confDDFilesToWrite) { ddFile.setArchiveType(getModuleType()); - try (OutputStream os = out.putNextEntry(ddFile.getDeploymentDescriptorPath())) { + try (WritableArchiveEntry os = out.putNextEntry(ddFile.getDeploymentDescriptorPath())) { ddFile.write(desc, os); } } diff --git a/appserver/deployment/dol/src/main/java/com/sun/enterprise/deployment/archivist/DescriptorArchivist.java b/appserver/deployment/dol/src/main/java/com/sun/enterprise/deployment/archivist/DescriptorArchivist.java index acdcb5b9346..cf2753c5e38 100644 --- a/appserver/deployment/dol/src/main/java/com/sun/enterprise/deployment/archivist/DescriptorArchivist.java +++ b/appserver/deployment/dol/src/main/java/com/sun/enterprise/deployment/archivist/DescriptorArchivist.java @@ -60,8 +60,8 @@ public void write(Application application, ReadableArchive in, WritableArchive o // let's start by writing out all submodules deployment descriptors for (ModuleDescriptor aModule : application.getModules()) { Archivist moduleArchivist = archivistFactory.getArchivist(aModule.getModuleType()); - WritableArchive moduleArchive = out.createSubArchive(aModule.getArchiveUri()); - try (ReadableArchive moduleArchive2 = in.getSubArchive(aModule.getArchiveUri())) { + try (WritableArchive moduleArchive = out.createSubArchive(aModule.getArchiveUri()); + ReadableArchive moduleArchive2 = in.getSubArchive(aModule.getArchiveUri())) { write(aModule.getDescriptor(), moduleArchivist, moduleArchive2, moduleArchive); } } diff --git a/appserver/deployment/dol/src/main/java/com/sun/enterprise/deployment/archivist/ExtensionsArchivist.java b/appserver/deployment/dol/src/main/java/com/sun/enterprise/deployment/archivist/ExtensionsArchivist.java index cef4a40dde7..2e2f5f41586 100644 --- a/appserver/deployment/dol/src/main/java/com/sun/enterprise/deployment/archivist/ExtensionsArchivist.java +++ b/appserver/deployment/dol/src/main/java/com/sun/enterprise/deployment/archivist/ExtensionsArchivist.java @@ -25,7 +25,6 @@ import java.io.IOException; import java.io.InputStream; -import java.io.OutputStream; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; @@ -33,6 +32,7 @@ import org.glassfish.api.deployment.archive.ArchiveType; import org.glassfish.api.deployment.archive.ReadableArchive; import org.glassfish.api.deployment.archive.WritableArchive; +import org.glassfish.api.deployment.archive.WritableArchiveEntry; import org.glassfish.deployment.common.RootDeploymentDescriptor; import org.jvnet.hk2.annotations.Contract; import org.xml.sax.SAXException; @@ -205,7 +205,7 @@ public void writeDeploymentDescriptors(Archivist main, BundleDescriptor descript public void writeStandardDeploymentDescriptors(Archivist main, BundleDescriptor descriptor, WritableArchive out) throws IOException { getStandardDDFile(descriptor).setArchiveType(main.getModuleType()); - try (OutputStream os = out.putNextEntry(standardDD.getDeploymentDescriptorPath())) { + try (WritableArchiveEntry os = out.putNextEntry(standardDD.getDeploymentDescriptorPath())) { standardDD.write(descriptor, os); } } @@ -228,7 +228,7 @@ public void writeRuntimeDeploymentDescriptors(Archivist main, BundleDescriptor d } for (ConfigurationDeploymentDescriptorFile ddFile : confDDFilesToWrite) { ddFile.setArchiveType(main.getModuleType()); - try (OutputStream os = out.putNextEntry(ddFile.getDeploymentDescriptorPath())) { + try (WritableArchiveEntry os = out.putNextEntry(ddFile.getDeploymentDescriptorPath())) { ddFile.write(descriptor, os); } } diff --git a/appserver/deployment/jakartaee-full/src/main/java/org/glassfish/javaee/full/deployment/EarDeployer.java b/appserver/deployment/jakartaee-full/src/main/java/org/glassfish/javaee/full/deployment/EarDeployer.java index 49d8a1ad11d..18ef1cde056 100644 --- a/appserver/deployment/jakartaee-full/src/main/java/org/glassfish/javaee/full/deployment/EarDeployer.java +++ b/appserver/deployment/jakartaee-full/src/main/java/org/glassfish/javaee/full/deployment/EarDeployer.java @@ -111,10 +111,7 @@ public class EarDeployer implements Deployer { @LogMessageInfo(message = "Skipped processing for module {0} as its module type was not recognized", level = "WARNING") private static final String UNRECOGNIZED_MODULE_TYPE = "AS-DEPLOYMENT-02015"; - @LogMessageInfo(message = "Error occurred", level = "WARNING") - private static final String ERROR_OCCURRED = "AS-DEPLOYMENT-02016"; - - final private static LocalStringManagerImpl localStrings = new LocalStringManagerImpl(EarDeployer.class); + private static final LocalStringManagerImpl localStrings = new LocalStringManagerImpl(EarDeployer.class); @Override public MetaData getMetaData() { @@ -267,21 +264,16 @@ private ModuleInfo prepareBundle(final ModuleDescriptor md, Application applicat List> orderedContainers = null; - ProgressTracker tracker = bundleContext.getTransientAppMetaData(ExtendedDeploymentContext.TRACKER, ProgressTracker.class); - - try { - // let's get the previously stored list of sniffers - Hashtable> sniffersTable = bundleContext.getSource().getParentArchive() - .getExtraData(Hashtable.class); - Collection sniffers = sniffersTable.get(md.getArchiveUri()); - // let's get the list of containers interested in this module - orderedContainers = deployment.setupContainerInfos(null, sniffers, bundleContext); - if (orderedContainers == null) { - return null; - } - } catch (Exception e) { - deplLogger.log(Level.WARNING, ERROR_OCCURRED, e); - throw e; + ProgressTracker tracker = bundleContext.getTransientAppMetaData(ExtendedDeploymentContext.TRACKER, + ProgressTracker.class); + // let's get the previously stored list of sniffers + Hashtable> sniffersTable = bundleContext.getSource().getParentArchive() + .getExtraData(Hashtable.class); + Collection sniffers = sniffersTable.get(md.getArchiveUri()); + // let's get the list of containers interested in this module + orderedContainers = deployment.setupContainerInfos(null, sniffers, bundleContext); + if (orderedContainers == null) { + return null; } return deployment.prepareModule(orderedContainers, md.getArchiveUri(), bundleContext, tracker); } @@ -312,13 +304,12 @@ private ExtendedDeploymentContext subContext(final Application application, fina return moduleContext; } - // FIXME: never closed final ReadableArchive subArchive; try { subArchive = context.getSource().getSubArchive(moduleUri); subArchive.setParentArchive(context.getSource()); } catch (IOException ioe) { - deplLogger.log(Level.WARNING, ERROR_OCCURRED, ioe); + deplLogger.log(Level.WARNING, "Could not work with subarchive for " + moduleUri, ioe); return null; } diff --git a/appserver/deployment/jakartaee-full/src/main/java/org/glassfish/javaee/full/deployment/EarHandler.java b/appserver/deployment/jakartaee-full/src/main/java/org/glassfish/javaee/full/deployment/EarHandler.java index a3d1c31ce1c..7ad060c5ebd 100644 --- a/appserver/deployment/jakartaee-full/src/main/java/org/glassfish/javaee/full/deployment/EarHandler.java +++ b/appserver/deployment/jakartaee-full/src/main/java/org/glassfish/javaee/full/deployment/EarHandler.java @@ -407,9 +407,7 @@ public File getScratchDir(String subDirName) { ClassLoader subCl = handler.getClassLoader(cl, subContext); if (System.getSecurityManager() != null && (subCl instanceof DDPermissionsLoader)) { addEEOrDeclaredPermissions(subCl, earDeclaredPC, false); - if (_logger.isLoggable(Level.FINE)) { - _logger.fine("added declared permissions to sub module of " + subCl); - } + _logger.log(Level.FINE, "added declared permissions to sub module of {0}", subCl); } if (md.getModuleType().equals(DOLUtils.ejbType())) { diff --git a/appserver/persistence/jpa-container/src/main/java/org/glassfish/persistence/jpa/JPADeployer.java b/appserver/persistence/jpa-container/src/main/java/org/glassfish/persistence/jpa/JPADeployer.java index 06e40d6e075..12560f985fb 100644 --- a/appserver/persistence/jpa-container/src/main/java/org/glassfish/persistence/jpa/JPADeployer.java +++ b/appserver/persistence/jpa-container/src/main/java/org/glassfish/persistence/jpa/JPADeployer.java @@ -198,7 +198,6 @@ public void event(Event event) { // an application-ref is being created on DAS. Process the app if (!deployCommandParameters.origin.isCreateAppRef() || isTargetDas(deployCommandParameters)) { Map deploymentContexts = context.getModuleDeploymentContexts(); - for (DeploymentContext deploymentContext : deploymentContexts.values()) { // bundle level pus iterateInitializedPUsAtApplicationPrepare(deploymentContext); @@ -302,7 +301,7 @@ void visitPUD(PersistenceUnitDescriptor pud, DeploymentContext context) { // Provide users an option to disable weaving by passing the flag. // Note that we enable weaving if not explicitly disabled by user boolean weavingEnabled = Boolean - .valueOf(startupContext.getArguments().getProperty("org.glassfish.persistence.embedded.weaving.enabled", "true")); + .parseBoolean(startupContext.getArguments().getProperty("org.glassfish.persistence.embedded.weaving.enabled", "true")); ProviderContainerContractInfo providerContainerContractInfo = weavingEnabled ? new ServerProviderContainerContractInfo(context, connectorRuntime, isDas) diff --git a/nucleus/common/common-util/src/main/java/com/sun/enterprise/util/io/FileUtils.java b/nucleus/common/common-util/src/main/java/com/sun/enterprise/util/io/FileUtils.java index 1b075775250..5af6ec5c685 100644 --- a/nucleus/common/common-util/src/main/java/com/sun/enterprise/util/io/FileUtils.java +++ b/nucleus/common/common-util/src/main/java/com/sun/enterprise/util/io/FileUtils.java @@ -657,6 +657,7 @@ public static void copy(File fin, File fout) throws IOException { throw new RuntimeException("Can't create parent dir of output file: " + fout); } Files.copy(fin.toPath(), fout.toPath()); + LOG.log(Level.DEBUG, "Successfully copyied file {0} to {1}", fin, fout); } @@ -748,7 +749,7 @@ static boolean isValidString(String s) { * @throws IOException */ public static void copy(InputStream in, File out, long bytes) throws IOException { - try (ReadableByteChannel inputChannel = Channels.newChannel(new BufferedInputStream(in)); + try (ReadableByteChannel inputChannel = Channels.newChannel(in); FileOutputStream output = new FileOutputStream(out)) { output.getChannel().transferFrom(inputChannel, 0, bytes); } @@ -769,26 +770,29 @@ public static void copy(InputStream in, OutputStream os) throws IOException { if (outputChannel instanceof FileChannel) { // Can be optimized by the operating system FileChannel foch = (FileChannel) outputChannel; - foch.transferFrom(inputChannel, 0, Long.MAX_VALUE); + long transferred = foch.transferFrom(inputChannel, 0, Long.MAX_VALUE); + LOG.log(Level.TRACE, "Copyied {0} B via {1}", transferred, foch); + os.flush(); return; } - ByteBuffer byteBuffer = ByteBuffer.allocate(8192); + final ByteBuffer byteBuffer = ByteBuffer.allocate(8192); + long transferred = 0; int read; do { read = inputChannel.read(byteBuffer); - if (read > 0) { + if (read >= 0) { byteBuffer.flip(); outputChannel.write(byteBuffer); byteBuffer.clear(); + transferred += read; } } while (read != -1); + LOG.log(Level.TRACE, "Copyied {0} B via {1}", transferred, outputChannel); + os.flush(); } private static WritableByteChannel getChannel(final OutputStream stream) { - if (stream instanceof FileOutputStream) { - return ((FileOutputStream) stream).getChannel(); - } if (stream instanceof WritableArchiveEntry) { return ((WritableArchiveEntry) stream).getChannel(); } diff --git a/nucleus/common/common-util/src/main/java/org/glassfish/admin/payload/PayloadFilesManager.java b/nucleus/common/common-util/src/main/java/org/glassfish/admin/payload/PayloadFilesManager.java index 08804ce8d80..f725121ef1e 100644 --- a/nucleus/common/common-util/src/main/java/org/glassfish/admin/payload/PayloadFilesManager.java +++ b/nucleus/common/common-util/src/main/java/org/glassfish/admin/payload/PayloadFilesManager.java @@ -20,13 +20,10 @@ import com.sun.enterprise.util.LocalStringManagerImpl; import com.sun.enterprise.util.io.FileUtils; -import java.io.BufferedOutputStream; import java.io.File; import java.io.FileNotFoundException; -import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; -import java.io.OutputStream; import java.io.UnsupportedEncodingException; import java.net.URI; import java.util.ArrayList; @@ -267,25 +264,13 @@ protected void postProcessParts() { */ public static class Temp extends PayloadFilesManager { -// /* -// * regex to match colons and backslashes on Windows and slashes on non-Windows -// */ -// private static final String DIR_PATH_TO_FLAT_NAME_PATTERN = (File.separatorChar == '\\') ? -// "[:\\\\]" : "/"; - private boolean isCleanedUp = false; -// /** maps payload part name paths (excluding name and type) to temp file subdirs */ -// private Map pathToTempSubdir = new HashMap(); - - public Temp(final File parentDir, final ActionReport report, - final Logger logger) throws IOException { - super(createTempFolder( - parentDir, - logger), - report, - logger); + public Temp(final File parentDir, final ActionReport report, final Logger logger) throws IOException { + super(createTempFolder(parentDir, logger), report, logger); } + + /** * Creates a new PayloadFilesManager for temporary files. * @param report results report to which extraction results will be appended @@ -330,52 +315,6 @@ protected void postExtract(File extractedFile) { protected void postProcessParts() { // no-op } - - -// private String getParentPath(String partName) { -// if (partName.endsWith("/")) { -// partName = partName.substring(0, partName.length() - 1); -// } -// int lastSlash = partName.lastIndexOf('/'); -// if (lastSlash != -1) { -// return partName.substring(0, lastSlash); -// } -// return null; -// } - -// URI getTempSubDirForPath(String path) throws IOException { -// /* -// * Convert the path (which is currently in URI form) to -// * the local file system form. -// */ -// path = path.replace('/', File.separatorChar); -// File tempSubDir = pathToTempSubdir.get(path); -// if (tempSubDir == null) { -// /* -// * Replace slashes (forward or backward) that are directory -// * separators and replace colons (from Windows devices) with single -// * dashes. This technique generates unique but flat directory -// * names so same-named files in different directories will -// * go to different directories. -// * -// * The extra dashes make sure the prefix meets createTempFile's reqts. -// * -// */ -// String tempDirPrefix = path.replaceAll(DIR_PATH_TO_FLAT_NAME_PATTERN, "-") + "---"; -// tempSubDir = createTempFolder(getTargetDir(), tempDirPrefix, super.logger); -// pathToTempSubdir.put(path, tempSubDir); -// } -// return tempSubDir.toURI(); -// } - -// private String getNameAndType(String path) { -// if (path.endsWith("/")) { -// path = path.substring(0, path.length() - 1); -// } -// final int lastSlash = path.lastIndexOf('/'); -// return path.substring(lastSlash + 1); -// } - } protected abstract void postExtract(final File extractedFile); @@ -463,105 +402,72 @@ private void processReport(final Payload.Part part) throws Exception { * @throws java.io.IOException */ private File extractFile(final Payload.Part part, final String outputName) throws IOException { - final boolean isFine = logger.isLoggable(Level.FINE); - OutputStream os = null; - InputStream is = null; - /* - * Look in the Part's properties first for the URI of the target - * directory for the file. If there is none there then use the - * target directory for this manager. - */ - - + // Look in the Part's properties first for the URI of the target + // directory for the file. If there is none there then use the + // target directory for this manager. try { File extractedFile = new File(getOutputFileURI(part, outputName)); - /* - * Create the required directory tree under the target directory. - */ + // Create the required directory tree under the target directory. File immediateParent = extractedFile.getParentFile(); - if ( ! immediateParent.exists() && ! immediateParent.mkdirs()) { + if (!immediateParent.exists() && !immediateParent.mkdirs()) { logger.log(Level.WARNING, strings.getLocalString( "payload.mkdirsFailed", "Attempt to create directories for {0} failed; no further information is available. Continuing.", - immediateParent.getAbsolutePath())); + immediateParent)); } if (extractedFile.exists()) { - if (!extractedFile.delete() && ! extractedFile.isDirectory()) { - /* - * Don't warn if we cannot delete the directory - there - * are likely to be files in it preventing its removal. - */ - logger.warning(strings.getLocalString( - "payload.overwrite", - "Overwriting previously-uploaded file because the attempt to delete it failed: {0}", - extractedFile.getAbsolutePath())); - } else if (isFine) { - logger.log(Level.FINER, "Deleted pre-existing file {0} before extracting transferred file", extractedFile.getAbsolutePath()); + if (!extractedFile.delete() && !extractedFile.isDirectory()) { + // Don't warn if we cannot delete the directory - there + // are likely to be files in it preventing its removal. + logger.warning(strings.getLocalString("payload.overwrite", + "Overwriting previously-uploaded file because the attempt to delete it failed: {0}", + extractedFile)); + } else { + logger.log(Level.FINER, "Deleted pre-existing file {0} before extracting transferred file", extractedFile); } } - /* - * If we are extracting a directory, then we need to consume the - * Part's body but we won't write anything into the directory - * file. - */ + // If we are extracting a directory, then we need to consume the + // Part's body but we won't write anything into the directory file. if (outputName.endsWith("/")) { - if ( ! extractedFile.exists() && ! extractedFile.mkdir()) { - logger.log(Level.WARNING, - strings.getLocalString("payload.mkdirsFailed", - "Attempt to create directories for {0} failed; no further information is available. Continuing.", - extractedFile.getAbsolutePath())); + if (!extractedFile.exists() && !extractedFile.mkdir()) { + logger.log(Level.WARNING, strings.getLocalString("payload.mkdirsFailed", + "Attempt to create directories for {0} failed; no further information is available. Continuing.", + extractedFile)); } } - final boolean isDir = extractedFile.isDirectory(); - - os = isDir ? null :new BufferedOutputStream(new FileOutputStream(extractedFile)); - is = part.getInputStream(); - int bytesRead; - byte[] buffer = new byte[1024 * 64]; - while ((bytesRead = is.read(buffer)) != -1) { - if (os != null) { - os.write(buffer, 0, bytesRead); + if (!extractedFile.isDirectory()) { + try (InputStream is = part.getInputStream()) { + FileUtils.copy(is, extractedFile, Long.MAX_VALUE); } } - if (os != null) { - os.close(); - } - /* This is because some commands need to process also stream payload - * parts more then ones. We have to tell that it was extracted to - * some file - */ + + // This is because some commands need to process also stream payload + // parts more then ones. We have to tell that it was extracted to some file part.setExtracted(extractedFile); final String lastModifiedString = part.getProperties().getProperty("last-modified"); - final long lastModified = (lastModifiedString != null ? - Long.parseLong(lastModifiedString) : - System.currentTimeMillis()); + final long lastModified = lastModifiedString == null ? System.currentTimeMillis() : Long.parseLong(lastModifiedString); - if ( ! extractedFile.setLastModified(lastModified)) { - logger.log(Level.WARNING, strings.getLocalString( - "payload.setLatModifiedFailed", + if (!extractedFile.setLastModified(lastModified)) { + logger.log(Level.WARNING, + strings.getLocalString("payload.setLatModifiedFailed", "Attempt to set lastModified for {0} failed; no further information is available. Continuing.", - extractedFile.getAbsolutePath())); + extractedFile)); } if (extractedFile.isDirectory()) { dirTimestamps.put(extractedFile, lastModified); } postExtract(extractedFile); - logger.log(Level.FINER, "Extracted transferred entry {0} to {1}", new Object[]{part.getName(), extractedFile.getAbsolutePath()}); + logger.log(Level.CONFIG, "Extracted transferred entry {0} of size {1} B to {2}", + new Object[] {part.getName(), extractedFile.length(), extractedFile}); reportExtractionSuccess(); return extractedFile; - } - catch (IOException e) { + } catch (IOException e) { reportExtractionFailure(part.getName(), e); throw new IOException(e.getMessage(), e); - } finally { - if (os != null) { - os.close(); - os = null; - } } } @@ -577,7 +483,7 @@ public Map processPartsExtended( final Payload.Inbound inboundPayload) throws Exception { if (inboundPayload == null) { - return Collections.EMPTY_MAP; + return Collections.emptyMap(); } final Map result = new LinkedHashMap<>(); diff --git a/nucleus/common/common-util/src/test/java/com/sun/enterprise/util/io/FileUtilsTest.java b/nucleus/common/common-util/src/test/java/com/sun/enterprise/util/io/FileUtilsTest.java index 720c8dce5e8..ec4cb2b1039 100644 --- a/nucleus/common/common-util/src/test/java/com/sun/enterprise/util/io/FileUtilsTest.java +++ b/nucleus/common/common-util/src/test/java/com/sun/enterprise/util/io/FileUtilsTest.java @@ -17,29 +17,41 @@ package com.sun.enterprise.util.io; +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; import java.io.File; - +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.InputStream; +import java.nio.file.Files; +import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; /** - * * @author wnevins + * @author David Matejcek */ public class FileUtilsTest { + private static File tempDir; + + @BeforeAll + public static void init() throws Exception { + tempDir = Files.createTempDirectory(FileUtilsTest.class.getSimpleName()).toFile(); + } - /** - * Test of mkdirsMaybe method, of class FileUtils. - */ @Test public void testMkdirsMaybe() { assertFalse(FileUtils.mkdirsMaybe(null)); File f = new File(".").getAbsoluteFile(); assertFalse(FileUtils.mkdirsMaybe(null)); File d1 = new File("junk" + System.currentTimeMillis()); + d1.deleteOnExit(); File d2 = new File("gunk" + System.currentTimeMillis()); + d2.deleteOnExit(); assertTrue(d1.mkdirs()); assertFalse(d1.mkdirs()); @@ -48,13 +60,55 @@ public void testMkdirsMaybe() { assertTrue(FileUtils.mkdirsMaybe(d2)); assertTrue(FileUtils.mkdirsMaybe(d2)); assertFalse(d2.mkdirs()); + } + + + @Test + public void testCopyFiles() throws Exception { + File outputFile = new File(tempDir, "outputFile"); + File testFile = new File(FileUtilsTest.class.getResource("/adminport.xml").toURI()); + FileUtils.copy(testFile, outputFile); + assertEquals(testFile.length(), outputFile.length()); + } + + + @Test + public void testCopyDirectoriesFiles() throws Exception { + File outputDir = new File(tempDir, "outputDir"); + File testDir = new File(FileUtilsTest.class.getResource("/process").toURI()); + FileUtils.copy(testDir, outputDir); + assertEquals(testDir.length(), outputDir.length()); + } + + + @Test + public void testCopyStreamToFile() throws Exception { + File outputFile = new File(tempDir, "outputFile"); + File testFile = new File(FileUtilsTest.class.getResource("/adminport.xml").toURI()); + FileInputStream stream = new FileInputStream(testFile); + FileUtils.copy(stream, outputFile, Long.MAX_VALUE); + assertEquals(testFile.length(), outputFile.length()); + } - if (!d1.delete()) { - d1.deleteOnExit(); - } - if (!d2.delete()) { - d2.deleteOnExit(); - } + @Test + public void testCopyFileStreamToFileStream() throws Exception { + File outputFile = new File(tempDir, "outputFile"); + FileOutputStream output = new FileOutputStream(outputFile); + File testFile = new File(FileUtilsTest.class.getResource("/adminport.xml").toURI()); + FileInputStream inputStream = new FileInputStream(testFile); + FileUtils.copy(inputStream, output); + assertEquals(testFile.length(), outputFile.length()); + } + + + @Test + public void testCopyCLStreamToStream() throws Exception { + File outputFile = new File(tempDir, "outputFile"); + BufferedOutputStream output = new BufferedOutputStream(new FileOutputStream(outputFile)); + File testFile = new File(FileUtilsTest.class.getResource("/adminport.xml").toURI()); + InputStream inputStream = new BufferedInputStream(FileUtilsTest.class.getResourceAsStream("/adminport.xml")); + FileUtils.copy(inputStream, output); + assertEquals(testFile.length(), outputFile.length()); } } diff --git a/nucleus/common/glassfish-api/src/main/java/org/glassfish/api/deployment/archive/Archive.java b/nucleus/common/glassfish-api/src/main/java/org/glassfish/api/deployment/archive/Archive.java index 9c8df416d00..bfda511b2ed 100644 --- a/nucleus/common/glassfish-api/src/main/java/org/glassfish/api/deployment/archive/Archive.java +++ b/nucleus/common/glassfish-api/src/main/java/org/glassfish/api/deployment/archive/Archive.java @@ -74,7 +74,7 @@ public interface Archive extends AutoCloseable { /** * Returns the manifest information for this archive * - * @return the manifest info + * @return the manifest info or null */ Manifest getManifest() throws IOException; diff --git a/nucleus/common/glassfish-api/src/main/java/org/glassfish/api/deployment/archive/WritableArchive.java b/nucleus/common/glassfish-api/src/main/java/org/glassfish/api/deployment/archive/WritableArchive.java index ab06f0f272b..9988f1fb91f 100644 --- a/nucleus/common/glassfish-api/src/main/java/org/glassfish/api/deployment/archive/WritableArchive.java +++ b/nucleus/common/glassfish-api/src/main/java/org/glassfish/api/deployment/archive/WritableArchive.java @@ -37,14 +37,6 @@ public interface WritableArchive extends Archive { */ void create(URI uri) throws IOException; - /** - * Close a previously returned sub archive - * - * @param subArchive output stream to close - * @see WritableArchive#createSubArchive(String) - */ - void closeEntry(WritableArchive subArchive) throws IOException; - /** * Create a new entry in the archive. Caller is responsible for closing the entry. * diff --git a/nucleus/common/glassfish-api/src/main/java/org/glassfish/api/deployment/archive/WritableArchiveEntry.java b/nucleus/common/glassfish-api/src/main/java/org/glassfish/api/deployment/archive/WritableArchiveEntry.java index 256db7e1bf0..dce8c2cd508 100644 --- a/nucleus/common/glassfish-api/src/main/java/org/glassfish/api/deployment/archive/WritableArchiveEntry.java +++ b/nucleus/common/glassfish-api/src/main/java/org/glassfish/api/deployment/archive/WritableArchiveEntry.java @@ -16,58 +16,66 @@ package org.glassfish.api.deployment.archive; -import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.nio.channels.Channels; import java.nio.channels.WritableByteChannel; -import java.util.zip.ZipOutputStream; +import java.util.function.Supplier; /** + * Archive entry used for the output. + * * @author David Matejcek */ public class WritableArchiveEntry extends OutputStream { - private final ZipOutputStream archive; - private final OutputStream output; + private final Supplier output; + private final CloseAction closeAction; /** - * @param archive owner of the archive entry - * @param output output stream to write to + * @param output provider of the output stream to write to + * @param closeAction what should do the entry when it is closing. */ - public WritableArchiveEntry(final ZipOutputStream archive, final OutputStream output) { - this.archive = archive; + public WritableArchiveEntry(Supplier output, CloseAction closeAction) { this.output = output; + this.closeAction = closeAction; } @Override public void write(int b) throws IOException { - output.write(b); + output.get().write(b); } /** - * @return output channel. No need to close it, it will be closed with this object. + * @return output channel. No need to close it, it will be closed by the original provider. */ public WritableByteChannel getChannel() { - if (output instanceof FileOutputStream) { - return ((FileOutputStream) output).getChannel(); - } - return Channels.newChannel(output); + OutputStream out = output.get(); + return Channels.newChannel(out); } @Override public void close() throws IOException { - if (archive == null) { - this.output.close(); - } else { - this.archive.flush(); - this.archive.finish(); - this.archive.closeEntry(); - } + closeAction.close(); + } + + + /** + * Action to close the entry. + */ + @FunctionalInterface + public interface CloseAction { + + /** + * Action to close the entry. + * + * @throws IOException + */ + void close() throws IOException; } } diff --git a/nucleus/core/kernel/src/main/java/com/sun/enterprise/v3/server/UpgradeStartup.java b/nucleus/core/kernel/src/main/java/com/sun/enterprise/v3/server/UpgradeStartup.java index f3970cf531a..5d3ccc11cd5 100644 --- a/nucleus/core/kernel/src/main/java/com/sun/enterprise/v3/server/UpgradeStartup.java +++ b/nucleus/core/kernel/src/main/java/com/sun/enterprise/v3/server/UpgradeStartup.java @@ -410,7 +410,7 @@ private File repackageApplication(File appDir, subModuleEntries.add(directoryEntry); File moduleJar = processModule(new File(appDir, directoryEntry), targetParentDir, null); try (InputStream is = new FileInputStream(moduleJar); - OutputStream os = target.putNextEntry(moduleJar.getName())) { + WritableArchiveEntry os = target.putNextEntry(moduleJar.getName())) { FileUtils.copy(is, os); } } diff --git a/nucleus/deployment/admin/src/main/java/org/glassfish/deployment/admin/DeployCommand.java b/nucleus/deployment/admin/src/main/java/org/glassfish/deployment/admin/DeployCommand.java index 01096c0a617..a0d3ecd42d0 100644 --- a/nucleus/deployment/admin/src/main/java/org/glassfish/deployment/admin/DeployCommand.java +++ b/nucleus/deployment/admin/src/main/java/org/glassfish/deployment/admin/DeployCommand.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, 2024 Contributors to the Eclipse Foundation. + * Copyright (c) 2022, 2024 Contributors to the Eclipse Foundation. * Copyright (c) 2008, 2018 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the @@ -17,61 +17,75 @@ package org.glassfish.deployment.admin; -import java.net.URI; -import java.net.URISyntaxException; -import com.sun.enterprise.config.serverbeans.*; +import com.sun.enterprise.config.serverbeans.Application; +import com.sun.enterprise.config.serverbeans.Applications; +import com.sun.enterprise.config.serverbeans.Cluster; +import com.sun.enterprise.config.serverbeans.Domain; +import com.sun.enterprise.config.serverbeans.Server; +import com.sun.enterprise.config.serverbeans.ServerTags; import com.sun.enterprise.deploy.shared.ArchiveFactory; import com.sun.enterprise.deploy.shared.FileArchive; import com.sun.enterprise.util.LocalStringManagerImpl; -import org.glassfish.admin.payload.PayloadImpl; -import org.glassfish.api.ActionReport; -import org.glassfish.api.I18n; -import org.glassfish.api.admin.AdminCommand; -import org.glassfish.api.admin.AdminCommandContext; -import org.glassfish.api.admin.CommandRunner; -import org.glassfish.api.admin.ExecuteOn; -import org.glassfish.api.admin.RuntimeType; -import org.glassfish.api.admin.ServerEnvironment; -import org.glassfish.api.deployment.DeployCommandParameters; -import org.glassfish.api.deployment.DeploymentContext; -import org.glassfish.api.deployment.archive.ArchiveHandler; -import org.glassfish.api.deployment.archive.ReadableArchive; -import org.glassfish.deployment.common.*; -import org.glassfish.internal.data.ApplicationInfo; -import org.glassfish.internal.deployment.*; -import org.glassfish.config.support.TargetType; -import org.glassfish.config.support.CommandTarget; -import org.jvnet.hk2.annotations.Contract; import jakarta.inject.Inject; -import org.jvnet.hk2.annotations.Service; -import org.glassfish.hk2.api.PerLookup; -import org.glassfish.hk2.api.ServiceLocator; -import org.jvnet.hk2.config.Transaction; - import java.io.File; import java.io.FileOutputStream; import java.io.IOException; -import java.util.*; +import java.net.URI; +import java.net.URISyntaxException; +import java.text.MessageFormat; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Properties; import java.util.logging.Level; import java.util.logging.Logger; +import org.glassfish.admin.payload.PayloadImpl; +import org.glassfish.api.ActionReport; import org.glassfish.api.ActionReport.ExitCode; -import org.glassfish.api.admin.AccessRequired; +import org.glassfish.api.I18n; import org.glassfish.api.admin.AccessRequired.AccessCheck; +import org.glassfish.api.admin.AdminCommand; +import org.glassfish.api.admin.AdminCommandContext; import org.glassfish.api.admin.AdminCommandSecurity; +import org.glassfish.api.admin.CommandRunner; +import org.glassfish.api.admin.ExecuteOn; import org.glassfish.api.admin.ParameterMap; import org.glassfish.api.admin.Payload; import org.glassfish.api.admin.RestEndpoint; import org.glassfish.api.admin.RestEndpoints; import org.glassfish.api.admin.RestParam; +import org.glassfish.api.admin.RuntimeType; +import org.glassfish.api.admin.ServerEnvironment; +import org.glassfish.api.deployment.DeployCommandParameters; +import org.glassfish.api.deployment.DeploymentContext; +import org.glassfish.api.deployment.archive.ArchiveHandler; +import org.glassfish.api.deployment.archive.ReadableArchive; import org.glassfish.api.event.EventListener; import org.glassfish.api.event.Events; +import org.glassfish.config.support.CommandTarget; +import org.glassfish.config.support.TargetType; +import org.glassfish.deployment.common.ApplicationConfigInfo; +import org.glassfish.deployment.common.Artifacts; +import org.glassfish.deployment.common.DeploymentContextImpl; +import org.glassfish.deployment.common.DeploymentProperties; +import org.glassfish.deployment.common.DeploymentUtils; +import org.glassfish.deployment.versioning.VersioningService; import org.glassfish.deployment.versioning.VersioningSyntaxException; import org.glassfish.deployment.versioning.VersioningUtils; - -import org.glassfish.deployment.versioning.VersioningService; +import org.glassfish.hk2.api.PerLookup; +import org.glassfish.hk2.api.ServiceLocator; +import org.glassfish.internal.data.ApplicationInfo; +import org.glassfish.internal.deployment.Deployment; +import org.glassfish.internal.deployment.DeploymentTracing; +import org.glassfish.internal.deployment.ExtendedDeploymentContext; +import org.glassfish.internal.deployment.SnifferManager; +import org.glassfish.internal.deployment.Verifier; +import org.jvnet.hk2.annotations.Contract; +import org.jvnet.hk2.annotations.Service; +import org.jvnet.hk2.config.Transaction; /** * Deploy command @@ -95,7 +109,7 @@ public class DeployCommand extends DeployCommandParameters implements AdminCommand, EventListener, AdminCommandSecurity.Preauthorization, AdminCommandSecurity.AccessCheckProvider { - final private static LocalStringManagerImpl localStrings = new LocalStringManagerImpl(DeployCommand.class); + private static final LocalStringManagerImpl localStrings = new LocalStringManagerImpl(DeployCommand.class); @Inject Applications apps; @@ -132,9 +146,9 @@ public class DeployCommand extends DeployCommandParameters implements AdminComma private File safeCopyOfAltDD = null; private File safeCopyOfRuntimeAltDD = null; private File originalPathValue; - private List previousTargets = new ArrayList(); - private Properties previousVirtualServers = new Properties(); - private Properties previousEnabledAttributes = new Properties(); + private List previousTargets = new ArrayList<>(); + private final Properties previousVirtualServers = new Properties(); + private final Properties previousEnabledAttributes = new Properties(); private Logger logger; private ExtendedDeploymentContext initialContext; private ExtendedDeploymentContext deploymentContext; @@ -249,9 +263,8 @@ public boolean preAuthorization(AdminCommandContext context) { ActionReport.MessagePart msgPart = context.getActionReport().getTopMessagePart(); msgPart.setChildrenType("WARNING"); ActionReport.MessagePart childPart = msgPart.addChild(); - childPart.setMessage(VersioningUtils.LOCALSTRINGS.getLocalString( - "versioning.deployment.osgi.warning", - "OSGi bundles will not use the GlassFish versioning, any version information embedded as part of the name option will be ignored")); + childPart.setMessage("OSGi bundles will not use the GlassFish versioning," + + " any version information embedded as part of the name option will be ignored"); name = VersioningUtils.getUntaggedName(name); } @@ -288,7 +301,7 @@ public boolean preAuthorization(AdminCommandContext context) { @Override public Collection getAccessChecks() { - final List accessChecks = new ArrayList(); + final List accessChecks = new ArrayList<>(); accessChecks.add(new AccessCheck(DeploymentCommandUtils.getResourceNameForApps(domain), "create")); accessChecks.add(new AccessCheck(DeploymentCommandUtils.getTargetResourceNameForNewAppRef(domain, target), "create")); @@ -339,8 +352,7 @@ public void execute(AdminCommandContext context) { if (!keepreposdir.booleanValue()) { final File reposDir = new File(env.getApplicationRepositoryPath(), VersioningUtils.getRepositoryName(name)); if (reposDir.exists()) { - List applications = domain.getApplications().getApplications(); - for (Application app : applications) { + for (Application app : domain.getApplications().getApplications()) { if (app.isLifecycleModule()) { continue; } @@ -381,12 +393,10 @@ public void execute(AdminCommandContext context) { // test if a version is already directory deployed from this dir String versionFromSameDir = versioningService.getVersionFromSameDir(source); if (!force && versionFromSameDir != null) { - report.failure(logger, - VersioningUtils.LOCALSTRINGS.getLocalString( - "versioning.deployment.dual.inplace", - "GlassFish do not support versioning for directory deployment when using the same directory. The directory {0} is already assigned to the version {1}.", - source.getPath(), - versionFromSameDir)); + report.failure(logger, MessageFormat.format( + "GlassFish do not support versioning for directory deployment when using the same directory." + + " The directory {0} is already assigned to the version {1}.", + source.getPath(), versionFromSameDir)); return; } } @@ -671,7 +681,7 @@ private Properties handleRedeploy(final String name, final ActionReport report, ActionReport subReport = report.addSubActionsReport(); subReport.setExtraProperties(new Properties()); - List propertyNames = new ArrayList(); + List propertyNames = new ArrayList<>(); propertyNames.add(DeploymentProperties.KEEP_SESSIONS); propertyNames.add(DeploymentProperties.PRESERVE_APP_SCOPED_RESOURCES); populatePropertiesToParameterMap(parameters, propertyNames); diff --git a/nucleus/deployment/admin/src/main/java/org/glassfish/deployment/admin/UndeployCommand.java b/nucleus/deployment/admin/src/main/java/org/glassfish/deployment/admin/UndeployCommand.java index 56b6b6e78c1..0fe4c82103c 100644 --- a/nucleus/deployment/admin/src/main/java/org/glassfish/deployment/admin/UndeployCommand.java +++ b/nucleus/deployment/admin/src/main/java/org/glassfish/deployment/admin/UndeployCommand.java @@ -17,46 +17,29 @@ package org.glassfish.deployment.admin; -import com.sun.enterprise.config.serverbeans.*; -import com.sun.enterprise.util.LocalStringManagerImpl; -import org.glassfish.internal.data.ApplicationInfo; -import org.glassfish.internal.data.ApplicationRegistry; -import org.glassfish.internal.deployment.Deployment; -import org.glassfish.internal.deployment.ExtendedDeploymentContext; -import org.glassfish.internal.deployment.DeploymentTargetResolver; -import com.sun.enterprise.deploy.shared.ArchiveFactory; import com.sun.enterprise.admin.util.ClusterOperationUtil; -import org.glassfish.deployment.common.DeploymentUtils; -import org.glassfish.deployment.common.DeploymentProperties; -import org.glassfish.api.ActionReport; -import org.glassfish.api.I18n; -import org.glassfish.api.event.Events; -import org.glassfish.api.event.EventListener.Event; -import org.glassfish.api.deployment.archive.ReadableArchive; -import org.glassfish.api.deployment.UndeployCommandParameters; -import org.glassfish.api.deployment.DeploymentContext; -import org.glassfish.config.support.TargetType; -import org.glassfish.config.support.CommandTarget; -import org.glassfish.common.util.admin.ParameterMapExtractor; -import jakarta.inject.Inject; -import org.jvnet.hk2.annotations.Service; +import com.sun.enterprise.config.serverbeans.Application; +import com.sun.enterprise.config.serverbeans.ApplicationRef; +import com.sun.enterprise.config.serverbeans.Applications; +import com.sun.enterprise.config.serverbeans.Domain; +import com.sun.enterprise.deploy.shared.ArchiveFactory; +import com.sun.enterprise.util.LocalStringManagerImpl; -import org.glassfish.hk2.api.PerLookup; -import org.glassfish.hk2.api.ServiceLocator; -import org.jvnet.hk2.config.TransactionFailure; +import jakarta.inject.Inject; import java.io.File; import java.io.IOException; -import java.util.logging.Logger; -import java.util.logging.Level; import java.net.URI; import java.net.URISyntaxException; -import java.util.ArrayList; import java.util.Collection; -import java.util.Iterator; +import java.util.Collections; import java.util.List; import java.util.Properties; -import java.util.Collections; +import java.util.logging.Level; +import java.util.logging.Logger; + +import org.glassfish.api.ActionReport; +import org.glassfish.api.I18n; import org.glassfish.api.admin.AccessRequired; import org.glassfish.api.admin.AdminCommand; import org.glassfish.api.admin.AdminCommandContext; @@ -69,10 +52,27 @@ import org.glassfish.api.admin.RestEndpoints; import org.glassfish.api.admin.RuntimeType; import org.glassfish.api.admin.ServerEnvironment; +import org.glassfish.api.deployment.UndeployCommandParameters; +import org.glassfish.api.deployment.archive.ReadableArchive; +import org.glassfish.api.event.EventListener.Event; +import org.glassfish.api.event.Events; +import org.glassfish.common.util.admin.ParameterMapExtractor; +import org.glassfish.config.support.CommandTarget; +import org.glassfish.config.support.TargetType; import org.glassfish.deployment.common.Artifacts; - -import org.glassfish.deployment.versioning.VersioningService; +import org.glassfish.deployment.common.DeploymentProperties; +import org.glassfish.deployment.common.DeploymentUtils; import org.glassfish.deployment.versioning.VersioningException; +import org.glassfish.deployment.versioning.VersioningService; +import org.glassfish.hk2.api.PerLookup; +import org.glassfish.hk2.api.ServiceLocator; +import org.glassfish.internal.data.ApplicationInfo; +import org.glassfish.internal.data.ApplicationRegistry; +import org.glassfish.internal.deployment.Deployment; +import org.glassfish.internal.deployment.DeploymentTargetResolver; +import org.glassfish.internal.deployment.ExtendedDeploymentContext; +import org.jvnet.hk2.annotations.Service; +import org.jvnet.hk2.config.TransactionFailure; /** * Undeploys applications. @@ -211,15 +211,10 @@ public Collection getAccessChecks() { domain, apps, target, matchedVersions, "delete", "delete"); } + @Override public void execute(AdminCommandContext context) { - - - // for each matched version - Iterator it = matchedVersions.iterator(); - while (it.hasNext()) { - String appName = (String)it.next(); - + for (String appName : matchedVersions) { if (target == null) { target = deployment.getDefaultTarget(appName, origin, _classicstyle); } @@ -352,7 +347,7 @@ public void execute(AdminCommandContext context) { try { final ParameterMapExtractor extractor = new ParameterMapExtractor(this); - final ParameterMap parameters = extractor.extract(Collections.EMPTY_LIST); + final ParameterMap parameters = extractor.extract(Collections.emptyList()); parameters.set("DEFAULT", appName); parameters.add(DeploymentProperties.IS_UNDEPLOY, Boolean.TRUE.toString()); inv.parameters(parameters).execute(); @@ -393,7 +388,7 @@ public void execute(AdminCommandContext context) { // check if it's directory deployment boolean isDirectoryDeployed = - Boolean.valueOf(application.getDirectoryDeployed()); + Boolean.parseBoolean(application.getDirectoryDeployed()); // we should try to unregister the application for both success // and warning case @@ -423,6 +418,7 @@ public void execute(AdminCommandContext context) { } } + @Override public String getTarget(ParameterMap parameters) { return DeploymentCommandUtils.getTarget(parameters, origin, deployment); } diff --git a/nucleus/deployment/common/src/main/java/com/sun/enterprise/deploy/shared/AbstractReadableArchive.java b/nucleus/deployment/common/src/main/java/com/sun/enterprise/deploy/shared/AbstractReadableArchive.java index 04ca2936f65..127b3051f1d 100644 --- a/nucleus/deployment/common/src/main/java/com/sun/enterprise/deploy/shared/AbstractReadableArchive.java +++ b/nucleus/deployment/common/src/main/java/com/sun/enterprise/deploy/shared/AbstractReadableArchive.java @@ -1,4 +1,5 @@ /* + * Copyright (c) 2022 Contributors to the Eclipse Foundation * Copyright (c) 2006, 2018 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the @@ -16,17 +17,18 @@ package com.sun.enterprise.deploy.shared; -import org.glassfish.api.deployment.archive.ReadableArchive; -import java.util.Map; import java.util.HashMap; +import java.util.Map; + +import org.glassfish.api.deployment.archive.ReadableArchive; /** * Common methods for ReadableArchive implementations */ public abstract class AbstractReadableArchive implements ReadableArchive { protected ReadableArchive parentArchive; - protected Map, Object> extraData=new HashMap, Object>(); - protected Map archiveMetaData = new HashMap(); + protected Map, Object> extraData=new HashMap<>(); + protected Map archiveMetaData = new HashMap<>(); /** @@ -34,6 +36,7 @@ public abstract class AbstractReadableArchive implements ReadableArchive { * * @param parentArchive the parent archive */ + @Override public void setParentArchive(ReadableArchive parentArchive) { this.parentArchive = parentArchive; } @@ -43,6 +46,7 @@ public void setParentArchive(ReadableArchive parentArchive) { * * @return the parent archive */ + @Override public ReadableArchive getParentArchive() { return parentArchive; } @@ -55,25 +59,30 @@ public ReadableArchive getParentArchive() { * @return the extra data or null if there are not an instance of * type dataType registered. */ + @Override public synchronized U getExtraData(Class dataType) { return dataType.cast(extraData.get(dataType)); } + @Override public synchronized void setExtraData(Class dataType, U instance) { extraData.put(dataType, instance); } + @Override public synchronized void removeExtraData(Class dataType) { extraData.remove(dataType); } + @Override public void addArchiveMetaData(String metaDataKey, Object metaData) { if (metaData!=null) { archiveMetaData.put(metaDataKey, metaData); } } + @Override public T getArchiveMetaData(String metaDataKey, Class metadataType) { Object metaData = archiveMetaData.get(metaDataKey); if (metaData != null) { @@ -82,7 +91,13 @@ public T getArchiveMetaData(String metaDataKey, Class metadataType) { return null; } + @Override public void removeArchiveMetaData(String metaDataKey) { archiveMetaData.remove(metaDataKey); } + + @Override + public String toString() { + return getClass().getSimpleName() + "[" + getName() + "]"; + } } diff --git a/nucleus/deployment/common/src/main/java/com/sun/enterprise/deploy/shared/ArchiveFactory.java b/nucleus/deployment/common/src/main/java/com/sun/enterprise/deploy/shared/ArchiveFactory.java index 29e93c46de6..cd96c2cdca7 100644 --- a/nucleus/deployment/common/src/main/java/com/sun/enterprise/deploy/shared/ArchiveFactory.java +++ b/nucleus/deployment/common/src/main/java/com/sun/enterprise/deploy/shared/ArchiveFactory.java @@ -177,7 +177,6 @@ public ReadableArchive openArchive(URI path) throws IOException { deplLogger.log(SEVERE, IMPLEMENTATION_NOT_FOUND, provider); throw new MalformedURLException("Protocol not supported : " + provider); } - archive.open(path); return archive; } catch (MultiException e) { diff --git a/nucleus/deployment/common/src/main/java/com/sun/enterprise/deploy/shared/FileArchive.java b/nucleus/deployment/common/src/main/java/com/sun/enterprise/deploy/shared/FileArchive.java index eaf5a35f92e..41b46dcf1db 100644 --- a/nucleus/deployment/common/src/main/java/com/sun/enterprise/deploy/shared/FileArchive.java +++ b/nucleus/deployment/common/src/main/java/com/sun/enterprise/deploy/shared/FileArchive.java @@ -114,6 +114,21 @@ public class FileArchive extends AbstractReadableArchive implements WritableArch */ private boolean isOpenedOrCreated; + /** + * Used just by HK2 + * + * @deprecated + */ + @Deprecated + public FileArchive() { + } + + + public FileArchive(URI uri) throws IOException { + open(uri); + } + + /** * Open an abstract archive * @@ -176,18 +191,6 @@ public void create(URI uri) throws IOException { isOpenedOrCreated = true; } - /** - * Close a previously returned sub archive - * - * @param subArchive output stream to close - * @link Archive.getSubArchive} - */ - @Override - public void closeEntry(WritableArchive subArchive) throws IOException { - subArchive.close(); - - } - /** * close the abstract archive */ @@ -223,10 +226,9 @@ public boolean isDirectory(String name) { * @return an @see java.util.Enumeration of entries in this abstract archive */ @Override - public Enumeration entries() { - final List namesList = new ArrayList(); + public Enumeration entries() { + final List namesList = new ArrayList<>(); getListOfFiles(archive, namesList, null); - return Collections.enumeration(namesList); } @@ -372,10 +374,9 @@ public boolean exists(String name) throws IOException { */ @Override public InputStream getEntry(String name) throws IOException { - + // If name corresponds to directory, return null as it can not be opened File input = getEntryFile(name); - if (!input.exists() || input.isDirectory() || !isEntryValid(input)) { // If name corresponds to directory, return null as it can not - // be opened + if (!input.exists() || input.isDirectory() || !isEntryValid(input)) { return null; } FileInputStream fis = new FileInputStream(input); @@ -383,12 +384,11 @@ public InputStream getEntry(String name) throws IOException { BufferedInputStream bis = new BufferedInputStream(fis); return bis; } catch (Throwable tx) { - if (fis != null) { - try { - fis.close(); - } catch (Throwable thr) { - throw new IOException("Error closing FileInputStream after error opening BufferedInputStream for entry " + name, thr); - } + try { + fis.close(); + } catch (Throwable thr) { + throw new IOException( + "Error closing FileInputStream after error opening BufferedInputStream for entry " + name, thr); } throw new IOException("Error opening BufferedInputStream for entry " + name, tx); } @@ -471,7 +471,8 @@ public WritableArchiveEntry putNextEntry(String name) throws java.io.IOException } } staleFileManager().recordValidEntry(newFile); - return new WritableArchiveEntry(null, new FileOutputStream(newFile)); + FileOutputStream outputStream = new FileOutputStream(newFile); + return new WritableArchiveEntry(() -> outputStream, outputStream::close); } /** @@ -494,11 +495,6 @@ public String getName() { return Util.getURIName(getURI()); } - @Override - public String toString() { - return getName(); - } - /** * @return true if this archive abstraction supports overwriting of elements * @@ -655,7 +651,7 @@ private boolean deleteDir(File directory) throws IOException { * utility method for getting contents of directory and sub directories */ - private void getListOfFiles(File directory, List files, List embeddedArchives) { + private void getListOfFiles(File directory, List files, List embeddedArchives) { getListOfFiles(directory, files, embeddedArchives, deplLogger); } @@ -668,7 +664,7 @@ private void getListOfFiles(File directory, List files, List embeddedArc * @param embeddedArchives collection of embedded archives in the current archive * @param logger logger to which to report inability to get the list of files from the directory */ - void getListOfFiles(File directory, List files, List embeddedArchives, final Logger logger) { + void getListOfFiles(File directory, List files, List embeddedArchives, final Logger logger) { if (archive == null || directory == null || !directory.isDirectory()) { return; } diff --git a/nucleus/deployment/common/src/main/java/com/sun/enterprise/deployment/deploy/shared/InputJarArchive.java b/nucleus/deployment/common/src/main/java/com/sun/enterprise/deployment/deploy/shared/InputJarArchive.java index f05fa30cf07..c6b7513e5b9 100644 --- a/nucleus/deployment/common/src/main/java/com/sun/enterprise/deployment/deploy/shared/InputJarArchive.java +++ b/nucleus/deployment/common/src/main/java/com/sun/enterprise/deployment/deploy/shared/InputJarArchive.java @@ -84,7 +84,18 @@ public class InputJarArchive extends JarArchive implements ReadableArchive { private InputJarArchive parentArchive; // track entry enumerations to close them if needed when the archive is closed - private final WeakHashMap entryEnumerations = new WeakHashMap(); + private final WeakHashMap entryEnumerations = new WeakHashMap<>(); + + public InputJarArchive(File file) throws IOException { + open(file.toURI()); + } + + /** + * Used also by HK2 + */ + public InputJarArchive() { + // see getSubArchive + } /** * Open an abstract archive @@ -122,7 +133,7 @@ public long getArchiveSize() throws NullPointerException, SecurityException { */ @Override public Collection getDirectories() throws IOException { - return new CollectionWrappedEnumeration(new CollectionWrappedEnumeration.EnumerationFactory() { + return new CollectionWrappedEnumeration<>(new CollectionWrappedEnumeration.EnumerationFactory() { @Override public Enumeration enumeration() { @@ -566,9 +577,9 @@ private interface JarEntrySource { */ private static class ArchiveJarEntrySource implements JarEntrySource { - private JarFile sourceJarFile; + private final JarFile sourceJarFile; - private Enumeration jarEntries; + private final Enumeration jarEntries; private ArchiveJarEntrySource(final URI archiveURI) throws IOException { sourceJarFile = getJarFile(archiveURI); @@ -594,7 +605,7 @@ public void close() throws IOException { */ private static class SubarchiveJarEntrySource implements JarEntrySource { - private JarInputStream jis; + private final JarInputStream jis; private SubarchiveJarEntrySource(final JarFile jf, final URI uri) throws IOException { final JarEntry subarchiveJarEntry = jf.getJarEntry(uri.getSchemeSpecificPart()); @@ -701,8 +712,8 @@ static class CollectionWrappedEnumeration extends AbstractCollection { private Enumeration e; - static interface EnumerationFactory { - public Enumeration enumeration(); + interface EnumerationFactory { + Enumeration enumeration(); } CollectionWrappedEnumeration(final EnumerationFactory factory) { @@ -712,7 +723,7 @@ static interface EnumerationFactory { @Override public Iterator iterator() { - return new Iterator() { + return new Iterator<>() { @Override public boolean hasNext() { @@ -746,12 +757,11 @@ public int size() { if (entries == null) { populateEntries(); } - ; return entries.size(); } private void populateEntries() { - entries = new ArrayList(); + entries = new ArrayList<>(); /* * Fill up the with data from a new enumeration. */ diff --git a/nucleus/deployment/common/src/main/java/com/sun/enterprise/deployment/deploy/shared/JarArchive.java b/nucleus/deployment/common/src/main/java/com/sun/enterprise/deployment/deploy/shared/JarArchive.java index 16ee38e71ff..6f7a21018d4 100644 --- a/nucleus/deployment/common/src/main/java/com/sun/enterprise/deployment/deploy/shared/JarArchive.java +++ b/nucleus/deployment/common/src/main/java/com/sun/enterprise/deployment/deploy/shared/JarArchive.java @@ -37,9 +37,9 @@ public abstract class JarArchive implements Archive { protected ReadableArchive parentArchive; - protected Map, Object> extraData = new HashMap, Object>(); + protected Map, Object> extraData = new HashMap<>(); - protected Map archiveMetaData = new HashMap(); + protected Map archiveMetaData = new HashMap<>(); /** * Returns an enumeration of the module file entries with the specified prefix. All elements in the enumeration are of @@ -51,7 +51,7 @@ public abstract class JarArchive implements Archive { @Override public Enumeration entries(String prefix) { Enumeration allEntries = entries(); - Vector entries = new Vector(); + Vector entries = new Vector<>(); while (allEntries.hasMoreElements()) { String name = allEntries.nextElement(); if (name != null && name.startsWith(prefix)) { @@ -168,4 +168,9 @@ public T getArchiveMetaData(String metaDataKey, Class metadataType) { public void removeArchiveMetaData(String metaDataKey) { archiveMetaData.remove(metaDataKey); } + + @Override + public String toString() { + return getClass().getSimpleName() + "[" + getName() + "]"; + } } diff --git a/nucleus/deployment/common/src/main/java/com/sun/enterprise/deployment/deploy/shared/MemoryMappedArchive.java b/nucleus/deployment/common/src/main/java/com/sun/enterprise/deployment/deploy/shared/MemoryMappedArchive.java index 89cb582fabe..9fa8518dbc3 100644 --- a/nucleus/deployment/common/src/main/java/com/sun/enterprise/deployment/deploy/shared/MemoryMappedArchive.java +++ b/nucleus/deployment/common/src/main/java/com/sun/enterprise/deployment/deploy/shared/MemoryMappedArchive.java @@ -18,6 +18,7 @@ package com.sun.enterprise.deployment.deploy.shared; import com.sun.enterprise.util.io.FileUtils; + import java.io.BufferedInputStream; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; @@ -26,6 +27,8 @@ import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; +import java.lang.System.Logger; +import java.lang.System.Logger.Level; import java.net.URI; import java.util.Collection; import java.util.Enumeration; @@ -34,8 +37,6 @@ import java.util.jar.JarInputStream; import java.util.jar.JarOutputStream; import java.util.jar.Manifest; -import java.util.logging.Level; -import java.util.logging.Logger; import java.util.zip.ZipEntry; import org.glassfish.api.deployment.archive.ReadableArchive; @@ -48,6 +49,7 @@ @Service @PerLookup public class MemoryMappedArchive extends JarArchive implements ReadableArchive { + private static final Logger LOG = System.getLogger(MemoryMappedArchive.class.getName()); private URI uri; private byte[] file; @@ -67,6 +69,24 @@ public MemoryMappedArchive(byte[] bits) { file = bits; } + // copy constructor + public MemoryMappedArchive(ReadableArchive source) throws IOException { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + try (JarOutputStream jos = new JarOutputStream(baos)) { + for (Enumeration elements = source.entries(); elements.hasMoreElements();) { + String elementName = elements.nextElement(); + try (InputStream is = source.getEntry(elementName)) { + jos.putNextEntry(new ZipEntry(elementName)); + FileUtils.copy(is, jos); + } finally { + jos.flush(); + jos.closeEntry(); + } + } + } + file = baos.toByteArray(); + } + public byte[] getByteArray() { return file; } @@ -88,24 +108,6 @@ public void open(URI uri) throws IOException { } } - // copy constructor - public MemoryMappedArchive(ReadableArchive source) throws IOException { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - try (JarOutputStream jos = new JarOutputStream(baos)) { - for (Enumeration elements = source.entries(); elements.hasMoreElements();) { - String elementName = elements.nextElement(); - try (InputStream is = source.getEntry(elementName)) { - jos.putNextEntry(new ZipEntry(elementName)); - FileUtils.copy(is, jos); - } finally { - jos.flush(); - jos.closeEntry(); - } - } - } - file = baos.toByteArray(); - } - /** * close the abstract archive */ @@ -137,33 +139,31 @@ public Collection getDirectories() throws IOException { } private Vector entries(boolean directory) { - - Vector entries = new Vector(); - try { - JarInputStream jis = new JarInputStream(new ByteArrayInputStream(file)); + Vector entries = new Vector<>(); + try (JarInputStream jis = new JarInputStream(new ByteArrayInputStream(file))) { ZipEntry ze; while ((ze=jis.getNextEntry())!=null) { if (ze.isDirectory()==directory) { entries.add(ze.getName()); } } - jis.close(); - } catch(IOException ioe) { - Logger.getAnonymousLogger().log(Level.WARNING, - ioe.getMessage(), ioe); + } catch (IOException ioe) { + LOG.log(Level.WARNING, ioe.getMessage(), ioe); } return entries; } - /** - * @return an @see java.util.Enumeration of entries in this abstract - * archive, providing the list of embedded archive to not count their - * entries as part of this archive - */ - public Enumeration entries(Enumeration embeddedArchives) { + + /** + * @return an @see java.util.Enumeration of entries in this abstract + * archive, providing the list of embedded archive to not count their + * entries as part of this archive + */ + public Enumeration entries(Enumeration embeddedArchives) { // jar file are not recursive return entries(); - } + } + /** * @return true if this archive exists @@ -186,7 +186,7 @@ public String getPath() { */ @Override public long getArchiveSize() throws NullPointerException, SecurityException { - return(file.length); + return file.length; } @Override @@ -205,11 +205,11 @@ public void setURI(final URI uri) { */ @Override public ReadableArchive getSubArchive(String name) throws IOException { - InputStream is = getEntry(name); - if (is!=null) { - ReadableArchive archive = new MemoryMappedArchive(is); - is.close(); - return archive; + try (InputStream is = getEntry(name)) { + if (is != null) { + ReadableArchive archive = new MemoryMappedArchive(is); + return archive; + } } return null; } @@ -226,16 +226,17 @@ public boolean exists(String name) throws IOException { return (getEntry(name) != null); } + /** - * @return a @see java.io.InputStream for an existing entry in - * the current abstract archive * @param name the entry name + * @return an {@link InputStream} for an existing entry in the current abstract archive. + * The caller is responsible for closing. Can be null. */ @Override public InputStream getEntry(String name) throws IOException { JarInputStream jis = new JarInputStream(new ByteArrayInputStream(file)); ZipEntry ze; - while ((ze=jis.getNextEntry())!=null) { + while ((ze = jis.getNextEntry()) != null) { if (ze.getName().equals(name)) { return new BufferedInputStream(jis); } @@ -245,15 +246,14 @@ public InputStream getEntry(String name) throws IOException { @Override public JarEntry getJarEntry(String name) { - try { - JarInputStream jis = new JarInputStream(new ByteArrayInputStream(file)); + try (JarInputStream jis = new JarInputStream(new ByteArrayInputStream(file))) { JarEntry ze; - while ((ze=jis.getNextJarEntry())!=null) { + while ((ze = jis.getNextJarEntry()) != null) { if (ze.getName().equals(name)) { return ze; } } - } catch(IOException e) { + } catch (IOException e) { return null; } return null; @@ -267,16 +267,15 @@ public JarEntry getJarEntry(String name) { */ @Override public long getEntrySize(String name) { - try { - JarInputStream jis = new JarInputStream(new ByteArrayInputStream(file)); + try (JarInputStream jis = new JarInputStream(new ByteArrayInputStream(file))) { ZipEntry ze; while ((ze=jis.getNextEntry())!=null) { if (ze.getName().equals(name)) { return ze.getSize(); } } - } catch(IOException e) { - return 0; + } catch (IOException e) { + LOG.log(Level.WARNING, "Couldn't get entry size for " + name + " in " + file, e); } return 0; } @@ -286,10 +285,9 @@ public long getEntrySize(String name) { */ @Override public Manifest getManifest() throws IOException { - JarInputStream jis = new JarInputStream(new ByteArrayInputStream(file)); - Manifest m = jis.getManifest(); - jis.close(); - return m; + try (JarInputStream jis = new JarInputStream(new ByteArrayInputStream(file))) { + return jis.getManifest(); + } } /** diff --git a/nucleus/deployment/common/src/main/java/com/sun/enterprise/deployment/deploy/shared/OutputJarArchive.java b/nucleus/deployment/common/src/main/java/com/sun/enterprise/deployment/deploy/shared/OutputJarArchive.java index 82400808164..9f37140d461 100644 --- a/nucleus/deployment/common/src/main/java/com/sun/enterprise/deployment/deploy/shared/OutputJarArchive.java +++ b/nucleus/deployment/common/src/main/java/com/sun/enterprise/deployment/deploy/shared/OutputJarArchive.java @@ -21,15 +21,16 @@ import java.io.File; import java.io.FileOutputStream; import java.io.IOException; +import java.lang.System.Logger; +import java.lang.System.Logger.Level; import java.net.URI; import java.net.URISyntaxException; +import java.text.MessageFormat; import java.util.Collection; import java.util.Enumeration; import java.util.Vector; import java.util.jar.JarEntry; import java.util.jar.Manifest; -import java.util.logging.Level; -import java.util.logging.Logger; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; @@ -47,6 +48,7 @@ @Service(name="jar") @PerLookup public class OutputJarArchive extends JarArchive implements WritableArchive { + private static final Logger LOG = System.getLogger(OutputJarArchive.class.getName()); // the path private URI uri; @@ -75,6 +77,7 @@ public long getArchiveSize() throws NullPointerException, SecurityException { @Override public void close() throws IOException { if (jos != null) { + LOG.log(Level.DEBUG, "close()"); jos.close(); jos = null; } @@ -85,29 +88,17 @@ protected JarEntry getJarEntry(String entryName) { return null; } - /** - * creates a new abstract archive with the given path - * - * @param path the path to create the archive - */ @Override public void create(URI path) throws IOException { + LOG.log(Level.DEBUG, "create(path={0})", path); this.uri = path; File file = new File(uri.getSchemeSpecificPart()); - // if teh file exists, we delete it first - if (file.exists()) { - boolean isDeleted = file.delete(); - if (!isDeleted) { - Logger.getAnonymousLogger().log(Level.WARNING, "Error in deleting file " + file.getAbsolutePath()); - } + if (file.exists() && !file.delete()) { + LOG.log(Level.WARNING, "Could not delete the file {0}", file); } jos = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(file))); } - /** - * @return an @see java.util.Enumeration of entries in this abstract - * archive - */ @Override public Enumeration entries() { return entries.elements(); @@ -119,9 +110,6 @@ public Collection getDirectories() throws IOException { } - /** - * @return the manifest information for this abstract archive - */ @Override public Manifest getManifest() throws IOException { if (manifest == null) { @@ -130,11 +118,6 @@ public Manifest getManifest() throws IOException { return manifest; } - /** - * Returns the path used to create or open the underlyong archive - * - * @return the path for this archive. - */ @Override public URI getURI() { return uri; @@ -142,6 +125,8 @@ public URI getURI() { @Override public WritableArchive createSubArchive(String name) throws IOException { + LOG.log(Level.DEBUG, "createSubArchive(name={0})", name); + checkOpen("Could not create subarchive {0}, because the output archive {1} is already closed.", name, getName()); ZipOutputStream zip = new ZipOutputStream(putNextEntry(name)); OutputJarArchive jar = new OutputJarArchive(); try { @@ -153,34 +138,35 @@ public WritableArchive createSubArchive(String name) throws IOException { return jar; } - /** - * Close a previously returned sub archive - * - * @param subArchive output stream to close - * @see WritableArchive#createSubArchive(String) - */ + @Override - public void closeEntry(WritableArchive subArchive) throws IOException { - if (subArchive instanceof OutputJarArchive) { - ((OutputJarArchive) subArchive).jos.flush(); - ((OutputJarArchive) subArchive).jos.finish(); - } + public WritableArchiveEntry putNextEntry(String name) throws java.io.IOException { + LOG.log(Level.DEBUG, "putNextEntry(name={0})", name); + checkOpen("Could not put next entry {0}, because the output archive {1} is already closed.", name, getName()); + ZipEntry ze = new ZipEntry(name); + jos.putNextEntry(ze); + entries.add(name); + return new WritableArchiveEntry(this::getZipOutputStream, this::closeEntry); + } + + + private void closeEntry() throws IOException { + LOG.log(Level.DEBUG, "closeEntry({0})", this.entries.get(this.entries.size() - 1)); + checkOpen("The zip output stream to {0} is already closed.", getName()); + jos.flush(); jos.closeEntry(); } - /** - * @param name the entry name - * @returns an @see java.io.OutputStream for a new entry in this - * current abstract archive. - */ - @Override - public WritableArchiveEntry putNextEntry(String name) throws java.io.IOException { - if (jos != null) { - ZipEntry ze = new ZipEntry(name); - jos.putNextEntry(ze); - entries.add(name); + private ZipOutputStream getZipOutputStream() { + checkOpen("The zip output stream to {0} is already closed.", getName()); + return jos; + } + + + private void checkOpen(String message, Object... args) { + if (jos == null) { + throw new IllegalStateException(MessageFormat.format(message, args)); } - return new WritableArchiveEntry(jos, jos); } } diff --git a/nucleus/deployment/common/src/main/java/org/glassfish/deployment/common/Artifacts.java b/nucleus/deployment/common/src/main/java/org/glassfish/deployment/common/Artifacts.java index b3d611b199c..2569fca6f53 100644 --- a/nucleus/deployment/common/src/main/java/org/glassfish/deployment/common/Artifacts.java +++ b/nucleus/deployment/common/src/main/java/org/glassfish/deployment/common/Artifacts.java @@ -1,4 +1,5 @@ /* + * Copyright (c) 2022 Contributors to the Eclipse Foundation * Copyright (c) 2006, 2018 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the @@ -22,9 +23,9 @@ import java.util.HashSet; import java.util.Properties; import java.util.Set; -import java.util.jar.JarFile; import java.util.logging.Level; import java.util.logging.Logger; + import org.glassfish.api.deployment.DeploymentContext; /** @@ -48,10 +49,10 @@ */ public class Artifacts { - public static final Logger deplLogger = org.glassfish.deployment.common.DeploymentContextImpl.deplLogger; + private static final Logger deplLogger = org.glassfish.deployment.common.DeploymentContextImpl.deplLogger; /** the actual artifacts tracked - the part URI and the full URI */ - private final Set artifacts = new HashSet(); + private final Set artifacts = new HashSet<>(); /** * used as part of the key in getting/setting transient DC metadata and @@ -59,28 +60,12 @@ public class Artifacts { */ private final String keyPrefix; - /** - * Returns the Artifacts object from the deployment context with the - * sepcified key prefix, creating a new one and storing it in the DC if - * no matching Artifacts object already exists. - * @param dc the deployment context - * @param keyPrefix key prefix by which to look up or store the artifacts - * @return - */ - public static Artifacts get( - final DeploymentContext dc, - final String keyPrefix) { - final String key = transientAppMetadataKey(keyPrefix); - synchronized (dc) { - Artifacts result = dc.getTransientAppMetaData( - transientAppMetadataKey(keyPrefix), Artifacts.class); + private Artifacts(final String keyPrefix) { + this.keyPrefix = keyPrefix; + } - if (result == null) { - result = new Artifacts(keyPrefix); - dc.addTransientAppMetaData(key, result); - } - return result; - } + private String propNamePrefix() { + return propNamePrefix(keyPrefix); } /** @@ -97,46 +82,32 @@ public void record(final DeploymentContext dc) { } } + /** - * Gets the artifacts matching the key prefix from the application properties - * of the specified application. - * @param app the application of interest - * @param keyPrefix type of artifacts of interest (e.g., downloadable, generated) - * @return + * Adds an artifact. + * + * @param full the full URI to the file to be tracked + * @param part the (typically) relative URI, expressed as a String, to be + * associated with the part */ - public static Artifacts get( - final Properties props, - final String keyPrefix) { - final Artifacts result = new Artifacts(keyPrefix); - - for (String propName : props.stringPropertyNames()) { - final String propNamePrefix = propNamePrefix(keyPrefix); - if (propName.startsWith(propNamePrefix)) { - /* - * The part URI is in the property name, after the keyPrefix and - * the separating dot. - */ - final URI fullURI = URI.create(props.getProperty(propName)); - result.addArtifact(fullURI, propName.substring(propNamePrefix.length())); - } - } - return result; - } - - private Artifacts(final String keyPrefix) { - this.keyPrefix = keyPrefix; + public synchronized void addArtifact(URI full, String part) { + addArtifact(full, URI.create(part)); } - private static String propNamePrefix(final String keyPrefix) { - return keyPrefix + "Artifact."; - } - private String propNamePrefix() { - return propNamePrefix(keyPrefix); + /** + * Adds an artifact. + * + * @param full the full URI to the file to be tracked + * @param part the (typically) relative URI to be associated with the part + */ + public synchronized void addArtifact(final URI full, final URI part) { + addArtifact(full, part, false); } /** * Adds an artifact. + * * @param full the full URI to the file to be tracked * @param part the (typically) relative URI to be associated with the part * @param isTemporary whether the artifact can be deleted once it is added to an output stream (typically for download) @@ -146,34 +117,9 @@ private String propNamePrefix() { public synchronized void addArtifact(URI full, URI part, boolean isTemporary) { FullAndPartURIs fullAndPart = new FullAndPartURIs(full, part, isTemporary); artifacts.add(fullAndPart); - if (deplLogger.isLoggable(Level.FINE)) { - deplLogger.log(Level.FINE, "Added {1} artifact: {0}", - new Object[] {fullAndPart, keyPrefix}); - } + deplLogger.log(Level.FINE, "Added {0} artifact: {1}", new Object[] {keyPrefix, fullAndPart}); } - /** - * Adds an artifact. - * @param full the full URI to the file to be tracked - * @param part the (typically) relative URI, expressed as a String, to be - * associated with the part - */ - public synchronized void addArtifact(URI full, String part) { - addArtifact(full, URI.create(part)); - } - - public synchronized void addArtifact(final URI full, final String part, final boolean isTemporary) { - addArtifact(full, URI.create(part), isTemporary); - } - - /** - * Adds an artifact. - * @param full - * @param part - */ - public synchronized void addArtifact(final URI full, final URI part) { - addArtifact(full, part, false); - } /** * Adds multiple artifacts at once. @@ -181,13 +127,7 @@ public synchronized void addArtifact(final URI full, final URI part) { */ public synchronized void addArtifacts(Collection urisCollection) { artifacts.addAll(urisCollection); - if (deplLogger.isLoggable(Level.FINE)) { - deplLogger.log(Level.FINE, "Added downloadable artifacts: {0}", urisCollection); - } - } - - private static String transientAppMetadataKey(final String prefix) { - return prefix + "Artifacts"; + deplLogger.log(Level.FINE, "Added downloadable artifacts: {0}", urisCollection); } private String transientAppMetadataKey() { @@ -203,8 +143,7 @@ private String propValue(final URI fullURI) { } /** - * Returns the URI pairs tracked by this Artifacts object. - * @return + * @return the actual artifacts tracked - the part URI and the full URI */ public synchronized Set getArtifacts() { return artifacts; @@ -216,12 +155,9 @@ public synchronized Set getArtifacts() { * @param props * @throws URISyntaxException */ - public synchronized void record( - final Properties props) throws URISyntaxException { + public synchronized void record(final Properties props) throws URISyntaxException { for (Artifacts.FullAndPartURIs artifactInfo : artifacts) { - props.setProperty( - propName(artifactInfo.getPart()), - propValue(artifactInfo.getFull())); + props.setProperty(propName(artifactInfo.getPart()), propValue(artifactInfo.getFull())); } } @@ -232,6 +168,58 @@ public synchronized void clearArtifacts() { artifacts.clear(); } + /** + * Returns the Artifacts object from the deployment context with the + * sepcified key prefix, creating a new one and storing it in the DC if + * no matching Artifacts object already exists. + * + * @param dc the deployment context + * @param keyPrefix key prefix by which to look up or store the artifacts + * @return never null + */ + public static Artifacts get(final DeploymentContext dc, final String keyPrefix) { + final String key = transientAppMetadataKey(keyPrefix); + synchronized (dc) { + Artifacts result = dc.getTransientAppMetaData(key, Artifacts.class); + if (result == null) { + result = new Artifacts(keyPrefix); + dc.addTransientAppMetaData(key, result); + } + return result; + } + } + + + /** + * Gets the artifacts matching the key prefix from the application properties + * of the specified application. + * + * @param props + * @param keyPrefix type of artifacts of interest (e.g., downloadable, generated) + * @return never null + */ + public static Artifacts get(final Properties props, final String keyPrefix) { + final Artifacts artifacts = new Artifacts(keyPrefix); + for (String propName : props.stringPropertyNames()) { + final String propNamePrefix = propNamePrefix(keyPrefix); + if (propName.startsWith(propNamePrefix)) { + // The part URI is in the property name, after the keyPrefix and the separating dot. + final URI fullURI = URI.create(props.getProperty(propName)); + artifacts.addArtifact(fullURI, propName.substring(propNamePrefix.length())); + } + } + return artifacts; + } + + private static String propNamePrefix(final String keyPrefix) { + return keyPrefix + "Artifact."; + } + + private static String transientAppMetadataKey(final String keyPrefix) { + return keyPrefix + "Artifacts"; + } + + /** * Represents a file to be tracked (the full URI) and a relative URI to be * associated with that file if is to be downloaded (e.g., as a part in diff --git a/nucleus/deployment/common/src/main/java/org/glassfish/deployment/common/ClientArtifactsManager.java b/nucleus/deployment/common/src/main/java/org/glassfish/deployment/common/ClientArtifactsManager.java index 218025e4f9f..b3a610b1104 100644 --- a/nucleus/deployment/common/src/main/java/org/glassfish/deployment/common/ClientArtifactsManager.java +++ b/nucleus/deployment/common/src/main/java/org/glassfish/deployment/common/ClientArtifactsManager.java @@ -1,4 +1,5 @@ /* + * Copyright (c) 2022 Contributors to the Eclipse Foundation * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the @@ -16,11 +17,11 @@ package org.glassfish.deployment.common; +import java.io.Closeable; import java.io.File; import java.io.IOException; import java.net.URI; import java.text.MessageFormat; -import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashMap; @@ -29,6 +30,7 @@ import java.util.jar.JarFile; import java.util.logging.Level; import java.util.logging.Logger; + import org.glassfish.api.deployment.DeploymentContext; import org.glassfish.logging.annotation.LogMessageInfo; @@ -63,11 +65,13 @@ * have been consumed and placed into the client JAR file, the add methods do not permit * further additions once the {@link #artifacts} method has been invoked. * + * FIXME This class is unable to control open resources and can cause IO leaks. + * * @author tjuinn */ -public class ClientArtifactsManager { +public class ClientArtifactsManager implements Closeable { - public static final Logger deplLogger = org.glassfish.deployment.common.DeploymentContextImpl.deplLogger; + private static final Logger LOG = org.glassfish.deployment.common.DeploymentContextImpl.deplLogger; @LogMessageInfo(message = "Artifact {0} identified for inclusion in app clients after one or more app clients were generated.", level="SEVERE", cause = "The application might specify that modules are to be processed in the order they appear in the application and an app client module appears before a module that creates an artifact to be included in app clients.", @@ -88,16 +92,15 @@ public class ClientArtifactsManager { private static final String CLIENT_ARTIFACTS_KEY = "ClientArtifacts"; - private final Map artifacts = - new HashMap(); + private final Map artifacts = new HashMap<>(); - /* + /** * To verify sources that are JAR entries we need to make sure the * requested entry exists in the specified JAR file. To optimize the * opening of JAR files we record the JARs previous checked * here. */ - private final Map jarFiles = new HashMap(); + private final Map jarFiles = new HashMap<>(); /** * Retrieves the client artifacts store from the provided deployment @@ -110,14 +113,12 @@ public class ClientArtifactsManager { */ public static ClientArtifactsManager get(final DeploymentContext dc) { synchronized (dc) { - ClientArtifactsManager result = dc.getTransientAppMetaData( - CLIENT_ARTIFACTS_KEY, ClientArtifactsManager.class); - - if (result == null) { - result = new ClientArtifactsManager(); - dc.addTransientAppMetaData(CLIENT_ARTIFACTS_KEY, result); + ClientArtifactsManager manager = dc.getTransientAppMetaData(CLIENT_ARTIFACTS_KEY, ClientArtifactsManager.class); + if (manager == null) { + manager = new ClientArtifactsManager(); + dc.addTransientAppMetaData(CLIENT_ARTIFACTS_KEY, manager); } - return result; + return manager; } } @@ -188,53 +189,38 @@ public boolean isEmpty() { * @param artifact */ public void add(Artifacts.FullAndPartURIs artifact) { - final boolean isLogAdditions = deplLogger.isLoggable(Level.FINE); + LOG.log(Level.FINEST, "add(artifact={0})", artifact); if (isArtifactSetConsumed) { throw new IllegalStateException( - formattedString(CLIENT_ARTIFACT_OUT_OF_ORDER, - artifact.getFull().toASCIIString()) + formattedString(CLIENT_ARTIFACT_OUT_OF_ORDER, artifact.getFull().toASCIIString())); + } + Artifacts.FullAndPartURIs existingArtifact = artifacts.get(artifact.getPart()); + if (existingArtifact != null) { + throw new IllegalArgumentException( + formattedString(CLIENT_ARTIFACT_COLLISION, + artifact.getPart().toASCIIString(), + artifact.getFull().toASCIIString(), + existingArtifact.getFull().toASCIIString()) ); + } + // Verify at add-time that we can read the specified source. + final String scheme = artifact.getFull().getScheme(); + if (scheme.equals("file")) { + verifyFileArtifact(artifact); + } else if (scheme.equals("jar")) { + verifyJarEntryArtifact(artifact); } else { - Artifacts.FullAndPartURIs existingArtifact = - artifacts.get(artifact.getPart()); - if (existingArtifact != null) { - throw new IllegalArgumentException( - formattedString(CLIENT_ARTIFACT_COLLISION, - artifact.getPart().toASCIIString(), - artifact.getFull().toASCIIString(), - existingArtifact.getFull().toASCIIString()) - ); - } - /* - * Verify at add-time that we can read the specified source. - */ - final String scheme = artifact.getFull().getScheme(); - if (scheme.equals("file")) { - verifyFileArtifact(artifact); - } else if (scheme.equals("jar")) { - verifyJarEntryArtifact(artifact); - } else { - throw new IllegalArgumentException(artifact.getFull().toASCIIString() + " != [file,jar]"); - } - if (isLogAdditions) { - final String stackTrace = (deplLogger.isLoggable(Level.FINER)) ? - Arrays.toString(Thread.currentThread().getStackTrace()) : ""; - deplLogger.log(Level.FINE, "ClientArtifactsManager added {0}\n{1}", - new Object[] {artifact, stackTrace}); - } - artifacts.put(artifact.getPart(), artifact); + throw new IllegalArgumentException(artifact.getFull().toASCIIString() + " != [file,jar]"); } + artifacts.put(artifact.getPart(), artifact); } private void verifyFileArtifact(final Artifacts.FullAndPartURIs artifact) { final URI fullURI = artifact.getFull(); final File f = new File(fullURI); - if ( ! f.exists() || ! f.canRead()) { + if (!f.exists() || !f.canRead()) { throw new IllegalArgumentException( - formattedString(CLIENT_ARTIFACT_MISSING, - artifact.getPart().toASCIIString(), - fullURI.toASCIIString()) - ); + formattedString(CLIENT_ARTIFACT_MISSING, artifact.getPart().toASCIIString(), fullURI.toASCIIString())); } } @@ -290,6 +276,7 @@ public boolean contains(final URI baseURI, final URI artifactURI) { public boolean contains(final File baseFile, final File artifactFile) { return contains(baseFile.toURI(), artifactFile.toURI()); } + /** * Returns the set (in unmodifiable form) of FullAndPartURIs for the * accumulated artifacts. @@ -301,12 +288,20 @@ public boolean contains(final File baseFile, final File artifactFile) { public Collection artifacts() { isArtifactSetConsumed = true; closeOpenedJARs(); - if (deplLogger.isLoggable(Level.FINE)) { - deplLogger.log(Level.FINE, "ClientArtifactsManager returned artifacts"); - } + LOG.log(Level.FINE, "ClientArtifactsManager returned artifacts"); return Collections.unmodifiableCollection(artifacts.values()); } + @Override + public void close() { + closeOpenedJARs(); + } + + private String formattedString(final String key, final Object... args) { + final String format = LOG.getResourceBundle().getString(key); + return MessageFormat.format(format, args); + } + private void closeOpenedJARs() { for (JarFile jarFile : jarFiles.values()) { try { @@ -318,19 +313,6 @@ private void closeOpenedJARs() { jarFiles.clear(); } - private String formattedString(final String key, final Object... args) { - final String format = deplLogger.getResourceBundle().getString(key); - return MessageFormat.format(format, args); - } - - @Override - protected void finalize() throws Throwable { - super.finalize(); //To change body of generated methods, choose Tools | Templates. - if ( ! isArtifactSetConsumed) { - closeOpenedJARs(); - } - } - /** * Represents a pair of URIs for an artifact, one being the URI where * the file already exists and one for the relative URI where the content diff --git a/nucleus/deployment/common/src/main/java/org/glassfish/deployment/common/ClientJarWriter.java b/nucleus/deployment/common/src/main/java/org/glassfish/deployment/common/ClientJarWriter.java index f45b79221bb..d1c3ebcfc12 100644 --- a/nucleus/deployment/common/src/main/java/org/glassfish/deployment/common/ClientJarWriter.java +++ b/nucleus/deployment/common/src/main/java/org/glassfish/deployment/common/ClientJarWriter.java @@ -21,11 +21,9 @@ import com.sun.enterprise.deployment.deploy.shared.OutputJarArchive; import com.sun.enterprise.util.io.FileUtils; -import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileInputStream; -import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; @@ -48,12 +46,10 @@ import org.glassfish.api.deployment.DeployCommandParameters; import org.glassfish.api.deployment.OpsParams; -import org.glassfish.api.deployment.archive.ReadableArchive; -import org.glassfish.api.deployment.archive.WritableArchive; import org.glassfish.api.deployment.archive.WritableArchiveEntry; +import org.glassfish.deployment.common.Artifacts.FullAndPartURIs; import org.glassfish.deployment.versioning.VersioningUtils; import org.glassfish.internal.deployment.ExtendedDeploymentContext; -import org.glassfish.logging.annotation.LogMessageInfo; /** * Writes a client JAR file, if one is needed, suitable for downloading. @@ -70,12 +66,8 @@ */ public class ClientJarWriter { - public static final Logger deplLogger = org.glassfish.deployment.common.DeploymentContextImpl.deplLogger; + private static final Logger LOG = org.glassfish.deployment.common.DeploymentContextImpl.deplLogger; - @LogMessageInfo(message = "Exception caught: {0}", level="WARNING") - private static final String EXCEPTION_CAUGHT = "NCLS-DEPLOYMENT-00004"; - - private final String LINE_SEP = System.getProperty("line.separator"); private final ExtendedDeploymentContext deploymentContext; private final String name; @@ -87,23 +79,20 @@ public ClientJarWriter(final ExtendedDeploymentContext deploymentContext) { } public void run() throws IOException { - /* - * Only generate the JAR if we would not already have done so. - */ + // Only generate the JAR if we would not already have done so. if (isArtifactsPresent()) { - deplLogger.log(Level.FINE, "Skipping possible client JAR generation because it would already have been done"); + LOG.log(Level.FINE, "Skipping possible client JAR generation because it would already have been done"); return; } - final Artifacts downloadableArtifacts = - DeploymentUtils.downloadableArtifacts(deploymentContext); - final Artifacts generatedArtifacts = - DeploymentUtils.generatedArtifacts(deploymentContext); - final File clientJarFile = createClientJARIfNeeded(deploymentContext, name); + final Artifacts downloadableArtifacts = DeploymentUtils.downloadableArtifacts(deploymentContext); + final Artifacts generatedArtifacts = DeploymentUtils.generatedArtifacts(deploymentContext); + final File clientJarFile = createClientJARIfNeeded(name); if (clientJarFile == null) { - deplLogger.log(Level.FINE, "No client JAR generation is needed."); + LOG.log(Level.FINE, "No client JAR generation is needed."); } else { - deplLogger.log(Level.FINE, "Generated client JAR {0} for possible download", clientJarFile.getAbsolutePath()); + LOG.log(Level.INFO, "Generated client JAR {0} for possible download of size {1} B", + new Object[] {clientJarFile, clientJarFile.length()}); downloadableArtifacts.addArtifact(clientJarFile.toURI(), clientJarFile.getName()); generatedArtifacts.addArtifact(clientJarFile.toURI(), clientJarFile.getName()); } @@ -113,124 +102,102 @@ private boolean isArtifactsPresent() { return deploymentContext.getCommandParameters(OpsParams.class).origin.isArtifactsPresent(); } - private File createClientJARIfNeeded(final ExtendedDeploymentContext deploymentContext, - final String appName) throws IOException { - final ClientArtifactsManager clientArtifactsManager = - ClientArtifactsManager.get(deploymentContext); + + private File createClientJARIfNeeded(final String appName) throws IOException { + LOG.log(Level.FINEST, "createClientJARIfNeeded(appName={0})", appName); + final ClientArtifactsManager clientArtifactsManager = ClientArtifactsManager.get(deploymentContext); if (clientArtifactsManager.isEmpty()) { return null; } - /* - * Make sure the scratch directories are there. - */ + // Make sure the scratch directories are there. deploymentContext.prepareScratchDirs(); final String generatedClientJARName = generatedClientJARNameAndType(appName); - final File generatedClientJARFile = new File(deploymentContext.getScratchDir("xml"), - generatedClientJARName); - /* - * The app client deployer might have already created the generated JAR - * file. In that case we need to merge its contents with what has been - * registered with the client artifacts manager. - */ - File movedPreexistingFile = null; + final File generatedClientJARFile = new File(deploymentContext.getScratchDir("xml"), generatedClientJARName); + + // The app client deployer might have already created the generated JAR file. + // In that case we need to merge its contents with what has been + // registered with the client artifacts manager. + final File movedPreexistingFile; if (generatedClientJARFile.exists()) { try { movedPreexistingFile = mergeContentsToClientArtifactsManager(generatedClientJARFile, clientArtifactsManager); + LOG.log(Level.FINEST, "Moved preexisting file: {0}", movedPreexistingFile); } catch (URISyntaxException ex) { throw new IOException(ex); } + } else { + movedPreexistingFile = null; } - /* - * We need our own copy of the artifacts collection because we might - * need to add the manifest to it if a manifst is not already in the collection. - * The client artifacts manager returns an unalterable collection. - */ + // We need our own copy of the artifacts collection because we might + // need to add the manifest to it if a manifst is not already in the collection. + // The client artifacts manager returns an unalterable collection. final Collection artifacts = new ArrayList<>(clientArtifactsManager.artifacts()); - - OutputJarArchive generatedClientJAR = new OutputJarArchive(); - try { - try { - generatedClientJAR.create(generatedClientJARFile.toURI()); - - if ( ! isManifestPresent(artifacts)) { - /* - * Add a simple manifest. - */ - deplLogger.log(Level.FINER, "Adding a simple manifest; one was not already generated"); - addManifest(artifacts); - } - - copyArtifactsToClientJAR(generatedClientJAR, artifacts); - } finally { - generatedClientJAR.close(); + try (OutputJarArchive generatedClientJAR = new OutputJarArchive()) { + generatedClientJAR.create(generatedClientJARFile.toURI()); + if (isManifestPresent(artifacts)) { + LOG.log(Level.FINEST, "The jar file already contains a manifest, no need to generate another."); + } else { + FullAndPartURIs manifest = generateManifest(); + LOG.log(Level.CONFIG, "Generated manifest: {0}", manifest); + artifacts.add(manifest); } - } catch (IOException ex) { - if ( ! generatedClientJARFile.delete()) { + copyArtifactsToClientJAR(generatedClientJAR, artifacts); + return generatedClientJARFile; + } catch (IOException e) { + if (!generatedClientJARFile.delete()) { generatedClientJARFile.deleteOnExit(); } + throw e; } finally { if (movedPreexistingFile != null) { FileUtils.deleteFileNowOrLater(movedPreexistingFile); } } - return generatedClientJARFile; } private File mergeContentsToClientArtifactsManager( final File generatedClientJARFile, final ClientArtifactsManager clientArtifactsManager) throws IOException, URISyntaxException { - /* - * First, move the existing JAR to another name so when the caller - * creates the generated client JAR it does not overwrite the existing - * file created by the app client deployer. - */ + // First, move the existing JAR to another name so when the caller creates the generated + // client JAR it does not overwrite the existing file created by the app client deployer. final File movedGeneratedFile = File.createTempFile(generatedClientJARFile.getName(), ".tmp", generatedClientJARFile.getParentFile()); FileUtils.renameFile(generatedClientJARFile, movedGeneratedFile); - final ReadableArchive existingGeneratedJAR = new InputJarArchive(); - existingGeneratedJAR.open(movedGeneratedFile.toURI()); - try { - for (Enumeration e = existingGeneratedJAR.entries(); e.hasMoreElements();) { - final String entryName = (String) e.nextElement(); + try (InputJarArchive existingGeneratedJAR = new InputJarArchive(movedGeneratedFile)) { + for (Enumeration e = existingGeneratedJAR.entries(); e.hasMoreElements();) { + final String entryName = e.nextElement(); final URI entryURI = new URI("jar", movedGeneratedFile.toURI().toASCIIString() + "!/" + entryName, null); final Artifacts.FullAndPartURIs uris = new Artifacts.FullAndPartURIs(entryURI, entryName); clientArtifactsManager.add(uris); } - /* - * Handle the manifest explicitly because the Archive entries() - * method consciously omits it. - */ + // Handle the manifest explicitly because the Archive entries() method consciously omits it. final Artifacts.FullAndPartURIs manifestURIs = new Artifacts.FullAndPartURIs( - new URI("jar", movedGeneratedFile.toURI().toASCIIString() + "!/" + JarFile.MANIFEST_NAME, null), JarFile.MANIFEST_NAME); + new URI("jar", movedGeneratedFile.toURI().toASCIIString() + "!/" + JarFile.MANIFEST_NAME, null), + JarFile.MANIFEST_NAME); clientArtifactsManager.add(manifestURIs); return movedGeneratedFile; - } finally { - existingGeneratedJAR.close(); } } private boolean isManifestPresent(final Collection artifacts) { - boolean isManifestPresent = false; - for (Artifacts.FullAndPartURIs a : artifacts) { - isManifestPresent |= a.getPart().toASCIIString().equals(JarFile.MANIFEST_NAME); + if (a.getPart().toASCIIString().equals(JarFile.MANIFEST_NAME)) { + return true; + } } - return isManifestPresent; + return false; } - private void addManifest(final Collection artifacts) throws IOException { + private Artifacts.FullAndPartURIs generateManifest() throws IOException { final File mfFile = File.createTempFile("clientmf", ".MF"); - final OutputStream mfOS = new BufferedOutputStream(new FileOutputStream(mfFile)); - try { + try (OutputStream mfOS = new BufferedOutputStream(new FileOutputStream(mfFile))) { final Manifest mf = new Manifest(); mf.getMainAttributes().put(Attributes.Name.MANIFEST_VERSION, "1.0"); mf.write(mfOS); - } finally { - mfOS.close(); } - artifacts.add(new Artifacts.FullAndPartURIs(mfFile.toURI(), JarFile.MANIFEST_NAME, true /* isTemporary */)); + return new Artifacts.FullAndPartURIs(mfFile.toURI(), JarFile.MANIFEST_NAME, true); } private static String generatedClientJARNameAndType(final String earName) { @@ -242,21 +209,18 @@ private static String generatedClientJARPrefix(final String earName) { } private void copyArtifactsToClientJAR( - final WritableArchive generatedClientJARArchive, + final OutputJarArchive generatedJar, final Collection artifacts) throws IOException { final Set pathsWrittenToJAR = new HashSet<>(); - StringBuilder copiedFiles = (deplLogger.isLoggable(Level.FINER)) ? new StringBuilder() : null; + final StringBuilder copiedFiles = LOG.isLoggable(Level.CONFIG) ? new StringBuilder() : null; for (Artifacts.FullAndPartURIs artifact : artifacts) { - /* - * Make sure all ancestor directories are present in the JAR - * as empty entries. - */ + // Make sure all ancestor directories are present in the JAR as empty entries. String artPath = artifact.getPart().getRawPath(); int previousSlash = artPath.indexOf('/'); while (previousSlash != -1) { String partialAncestorPath = artPath.substring(0, previousSlash + 1); if (!pathsWrittenToJAR.contains(partialAncestorPath)) { - try (WritableArchiveEntry entry = generatedClientJARArchive.putNextEntry(partialAncestorPath)) { + try (WritableArchiveEntry entry = generatedJar.putNextEntry(partialAncestorPath)) { // just an empty entry } pathsWrittenToJAR.add(partialAncestorPath); @@ -264,15 +228,15 @@ private void copyArtifactsToClientJAR( previousSlash = artPath.indexOf('/', previousSlash + 1); } - try (WritableArchiveEntry os = generatedClientJARArchive.putNextEntry(artifact.getPart().toASCIIString()); + try (WritableArchiveEntry entry = generatedJar.putNextEntry(artifact.getPart().toASCIIString()); InputStream is = openInputStream(artifact)) { - DeploymentUtils.copyStream(is, os); + FileUtils.copy(is, entry); if (copiedFiles != null) { - copiedFiles.append(LINE_SEP).append(" ").append(artifact.getFull().toASCIIString()).append(" -> ") - .append(artifact.getPart().toASCIIString()); + copiedFiles.append(System.lineSeparator()).append(" ").append(artifact.getFull().toASCIIString()) + .append(" -> ").append(artifact.getPart().toASCIIString()); } - } catch (Exception ex) { - deplLogger.log(Level.WARNING, EXCEPTION_CAUGHT, ex.getLocalizedMessage()); + } catch (Exception e) { + LOG.log(Level.WARNING, "Could not copy the entry " + artifact.getPart(), e); } finally { if (artifact.isTemporary()) { final File artifactFile = new File(artifact.getFull()); @@ -283,20 +247,20 @@ private void copyArtifactsToClientJAR( } } if (copiedFiles != null) { - deplLogger.log(Level.FINER, copiedFiles.toString()); + LOG.log(Level.CONFIG, "Copied files: {0}", copiedFiles); } } - private InputStream openInputStream(Artifacts.FullAndPartURIs artifact) - throws FileNotFoundException, URISyntaxException, IOException { + private InputStream openInputStream(Artifacts.FullAndPartURIs artifact) throws URISyntaxException, IOException { + LOG.log(Level.FINE, "openInputStream(artifact={0})", artifact); final URI fullURI = artifact.getFull(); final String scheme = fullURI.getScheme(); if (scheme.equals("file")) { - return new BufferedInputStream(new FileInputStream(new File(artifact.getFull()))); + return new FileInputStream(new File(fullURI)); } else if (scheme.equals("jar")) { final String ssp = fullURI.getSchemeSpecificPart(); - URI jarURI = new URI(ssp.substring(0, ssp.indexOf("!/"))); + final URI jarURI = new URI(ssp.substring(0, ssp.indexOf("!/"))); JarFile jf = jarFiles.get(jarURI); if (jf == null) { jf = new JarFile(new File(jarURI)); diff --git a/nucleus/deployment/common/src/main/java/org/glassfish/deployment/common/DeploymentContextImpl.java b/nucleus/deployment/common/src/main/java/org/glassfish/deployment/common/DeploymentContextImpl.java index 795313abc68..ff3a24b4a53 100644 --- a/nucleus/deployment/common/src/main/java/org/glassfish/deployment/common/DeploymentContextImpl.java +++ b/nucleus/deployment/common/src/main/java/org/glassfish/deployment/common/DeploymentContextImpl.java @@ -19,6 +19,7 @@ import com.sun.enterprise.util.LocalStringManagerImpl; +import java.io.Closeable; import java.io.File; import java.io.IOException; import java.lang.instrument.ClassFileTransformer; @@ -36,6 +37,7 @@ import java.util.Map; import java.util.Properties; import java.util.Set; +import java.util.logging.Level; import java.util.logging.Logger; import org.glassfish.api.ActionReport; @@ -63,7 +65,6 @@ import static java.util.logging.Level.FINEST; /** - * * @author dochez */ public class DeploymentContextImpl implements ExtendedDeploymentContext, PreDestroy { @@ -82,23 +83,23 @@ public class DeploymentContextImpl implements ExtendedDeploymentContext, PreDest private static final String INTERNAL_DIR_NAME = "__internal"; private static final String APP_TENANTS_SUBDIR_NAME = "__app-tenants"; - ReadableArchive source; - ReadableArchive originalSource; - final OpsParams parameters; - ActionReport actionReport; - final ServerEnvironment env; - ClassLoader cloader; - ArchiveHandler archiveHandler; - Properties props; - Map modulesMetaData = new HashMap<>(); - Phase phase = Phase.UNKNOWN; - ClassLoader sharableTemp; - Map modulePropsMap = new HashMap<>(); - Map transientAppMetaData = new HashMap<>(); - Map moduleArchiveHandlers = new HashMap<>(); - Map moduleDeploymentContexts = new HashMap<>(); - ExtendedDeploymentContext parentContext; - String moduleUri; + private ReadableArchive source; + private final ReadableArchive originalSource; + private final OpsParams parameters; + private ActionReport actionReport; + private final ServerEnvironment env; + private ClassLoader cloader; + private ArchiveHandler archiveHandler; + private Properties props; + private final Map modulesMetaData = new HashMap<>(); + private Phase phase = Phase.UNKNOWN; + private ClassLoader sharableTemp; + private Map modulePropsMap = new HashMap<>(); + private final Map transientAppMetaData = new HashMap<>(); + private final Map moduleArchiveHandlers = new HashMap<>(); + private final Map moduleDeploymentContexts = new HashMap<>(); + private ExtendedDeploymentContext parentContext; + private String moduleUri; private String tenant; private String originalAppName; private File tenantDir; @@ -157,6 +158,8 @@ public Logger getLogger() { @Override public synchronized void preDestroy() { + deplLogger.log(Level.FINEST, "preDestroy()"); + // FIXME: Is this really required? try { PreDestroy.class.cast(sharableTemp).preDestroy(); } catch (Exception e) { @@ -218,7 +221,6 @@ public synchronized void createDeploymentClassLoader(ClassLoaderHierarchy clh, A @Override public void createApplicationClassLoader(ClassLoaderHierarchy classLoaderHierarchy, ArchiveHandler handler) throws URISyntaxException, MalformedURLException { addTransientAppMetaData(IS_TEMP_CLASSLOADER, FALSE); - if (cloader == null) { cloader = createClassLoader(classLoaderHierarchy, handler, parameters.name()); } @@ -298,6 +300,7 @@ public File getSourceDir() { @Override public void addModuleMetaData(Object metaData) { + deplLogger.log(Level.FINEST, "addModuleMetaData(metaData={0})", metaData); if (metaData != null) { modulesMetaData.put(metaData.getClass().getName(), metaData); } @@ -332,6 +335,7 @@ public Map getTransientAppMetadata() { @Override public void addTransientAppMetaData(String metaDataKey, Object metaData) { + deplLogger.log(Level.FINEST, "addTransientAppMetaData(metaDataKey={0}, metaData)", metaDataKey); if (metaData != null) { transientAppMetaData.put(metaDataKey, metaData); } @@ -627,12 +631,21 @@ public File getTenantDir() { @Override public void postDeployClean(boolean isFinalClean) { + deplLogger.log(Level.FINEST, "postDeployClean(isFinalClean={0})", isFinalClean); if (transientAppMetaData != null) { if (isFinalClean) { + for (Object value : transientAppMetaData.values()) { + if (value instanceof Closeable) { + try { + ((Closeable) value).close(); + } catch (IOException e) { + deplLogger.log(Level.WARNING, "Close failed for " + value, e); + } + } + } transientAppMetaData.clear(); } else { final String[] classNamesToClean = { Types.class.getName(), Parser.class.getName() }; - for (String className : classNamesToClean) { transientAppMetaData.remove(className); } @@ -644,7 +657,7 @@ public void postDeployClean(boolean isFinalClean) { @Override public String toString() { - return (source == null ? "" : source.toString()) + " " + (originalSource == null ? "" : originalSource.getURI()); + return (source == null ? "" : source) + " " + (originalSource == null ? "" : originalSource.getURI()); } /** @@ -658,22 +671,17 @@ public void prepareScratchDirs() throws IOException { } - // ### Private methods - private File initTenantDir() { if (tenant == null || originalAppName == null) { return null; } - File tenantDir = new File(getRootTenantDirForApp(originalAppName), tenant); - if (!tenantDir.exists() && !tenantDir.mkdirs()) { - if (deplLogger.isLoggable(FINEST)) { - deplLogger.log(FINEST, "Unable to create directory " + tenantDir.getAbsolutePath()); - } - + File tenantDirectory = new File(getRootTenantDirForApp(originalAppName), tenant); + if (!tenantDirectory.exists() && !tenantDirectory.mkdirs()) { + deplLogger.log(FINEST, "Unable to create directory {0}", tenantDirectory.getAbsolutePath()); } - return tenantDir; + return tenantDirectory; } private File getRootTenantDirForApp(String appName) { diff --git a/nucleus/deployment/common/src/main/java/org/glassfish/deployment/common/DeploymentUtils.java b/nucleus/deployment/common/src/main/java/org/glassfish/deployment/common/DeploymentUtils.java index a62d2bae896..39c2e72730f 100644 --- a/nucleus/deployment/common/src/main/java/org/glassfish/deployment/common/DeploymentUtils.java +++ b/nucleus/deployment/common/src/main/java/org/glassfish/deployment/common/DeploymentUtils.java @@ -27,7 +27,6 @@ import java.io.File; import java.io.IOException; import java.io.InputStream; -import java.io.OutputStream; import java.net.URI; import java.net.URISyntaxException; import java.net.URL; @@ -67,17 +66,16 @@ /** * Utility methods for deployment. */ - public class DeploymentUtils { - public static final Logger deplLogger = DeploymentContextImpl.deplLogger; + private static final Logger deplLogger = DeploymentContextImpl.deplLogger; @LogMessageInfo(message = "Exception caught {0}", level = "WARNING") private static final String EXCEPTION_CAUGHT = "NCLS-DEPLOYMENT-00010"; public static final String DEPLOYMENT_PROPERTY_JAVA_WEB_START_ENABLED = "java-web-start-enabled"; - final private static LocalStringManagerImpl localStrings = new LocalStringManagerImpl(DeploymentUtils.class); + private static final LocalStringManagerImpl localStrings = new LocalStringManagerImpl(DeploymentUtils.class); private static final String V2_COMPATIBILITY = "v2"; @@ -319,7 +317,7 @@ public static void expand(ReadableArchive source, WritableArchive target) throws // Last is manifest if exists Manifest manifest = source.getManifest(); if (manifest != null) { - try (OutputStream entry = target.putNextEntry(MANIFEST_NAME)) { + try (WritableArchiveEntry entry = target.putNextEntry(MANIFEST_NAME)) { manifest.write(entry); } } @@ -466,12 +464,4 @@ public static String getVirtualServers(String target, ServerEnvironment env, Dom return virtualServers.toString(); } - - public static void copyStream(InputStream in, OutputStream out) throws IOException { - byte[] buf = new byte[4096]; - int len; - while ((len = in.read(buf)) >= 0) { - out.write(buf, 0, len); - } - } } diff --git a/nucleus/deployment/common/src/main/java/org/glassfish/deployment/versioning/VersioningService.java b/nucleus/deployment/common/src/main/java/org/glassfish/deployment/versioning/VersioningService.java index d9aeebfb8a2..5beebd5008c 100644 --- a/nucleus/deployment/common/src/main/java/org/glassfish/deployment/versioning/VersioningService.java +++ b/nucleus/deployment/common/src/main/java/org/glassfish/deployment/versioning/VersioningService.java @@ -1,4 +1,5 @@ /* + * Copyright (c) 2022 Contributors to the Eclipse Foundation * Copyright (c) 2008, 2018 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the @@ -16,27 +17,29 @@ package org.glassfish.deployment.versioning; -import com.sun.enterprise.config.serverbeans.Domain; import com.sun.enterprise.config.serverbeans.Application; +import com.sun.enterprise.config.serverbeans.Domain; + +import jakarta.inject.Inject; + import java.io.File; -import java.util.ArrayList; +import java.text.MessageFormat; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; -import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; + import javax.security.auth.Subject; + import org.glassfish.api.ActionReport; import org.glassfish.api.I18n; import org.glassfish.api.admin.CommandRunner; import org.glassfish.api.admin.ParameterMap; import org.glassfish.deployment.common.DeploymentUtils; -import jakarta.inject.Inject; - -import org.jvnet.hk2.annotations.Service; import org.glassfish.hk2.api.PerLookup; +import org.jvnet.hk2.annotations.Service; /** * This service provides methods to handle application names @@ -89,11 +92,8 @@ public Map> getEnabledVersionInReferencedTargetsForExpressio Map> enabledVersionsInTargets = Collections.EMPTY_MAP; List matchedVersions = getMatchedVersions(versionExpression, "domain"); - // foreach matched version - Iterator it = matchedVersions.iterator(); - while(it.hasNext()){ + for (String matchedVersion : matchedVersions) { - String matchedVersion = (String) it.next(); // retrieved all the enabled version on the referenced target on each matched version Map> tempMap = getEnabledVersionsInReferencedTargets(matchedVersion); @@ -131,14 +131,12 @@ public Map> getEnabledVersionsInReferencedTargets(String vers throws VersioningSyntaxException { Map> enabledVersionsInTargets = - new HashMap>(); + new HashMap<>(); List allTargets = domain.getAllReferencedTargetsForApplication(versionIdentifier); - Iterator it = allTargets.iterator(); - while(it.hasNext()){ - String target = (String)it.next(); + for (String target : allTargets) { String enabledVersion = getEnabledVersion(versionIdentifier, target); if(enabledVersion != null){ // the key already exists, we just add the new target into the list @@ -146,7 +144,7 @@ public Map> getEnabledVersionsInReferencedTargets(String vers enabledVersionsInTargets.get(enabledVersion).add(target); } else { // we have to create the list associated with the key - Set setTargets = new HashSet(); + Set setTargets = new HashSet<>(); setTargets.add(target); enabledVersionsInTargets.put(enabledVersion, setTargets); } @@ -171,11 +169,7 @@ public final String getEnabledVersion(String name, String target) List allVersions = getAllversions(untaggedName, target); if (allVersions != null) { - Iterator it = allVersions.iterator(); - - while (it.hasNext()) { - String app = (String) it.next(); - + for (String app : allVersions) { // if a version of the app is enabled if (domain.isAppEnabledInTarget(app, target)) { return app; @@ -205,11 +199,9 @@ public final List getMatchedVersions(String name, String target) // if versionned if(!name.equals(untagged)){ throw new VersioningException( - VersioningUtils.LOCALSTRINGS.getLocalString("versioning.deployment.application.noversion", - "Application {0} has no version registered", - untagged)); + MessageFormat.format("Application {0} has no version registered", untagged)); } - return Collections.EMPTY_LIST; + return Collections.emptyList(); } return VersioningUtils.matchExpression(allVersions, name); @@ -228,7 +220,7 @@ public final List getMatchedVersions(String name, String target) public void handleDisable(final String appName, final String target, final ActionReport report, final Subject subject) throws VersioningSyntaxException { - Set versionsToDisable = Collections.EMPTY_SET; + Set versionsToDisable = Collections.emptySet(); if (DeploymentUtils.isDomainTarget(target)) { // retrieve the enabled versions on each target in the domain @@ -244,14 +236,12 @@ public void handleDisable(final String appName, final String target, if (enabledVersion != null && !enabledVersion.equals(appName)) { - versionsToDisable = new HashSet(); + versionsToDisable = new HashSet<>(); versionsToDisable.add(enabledVersion); } } - Iterator it = versionsToDisable.iterator(); - while (it.hasNext()) { - String currentVersion = it.next(); + for (String currentVersion : versionsToDisable) { // invoke disable if the currently enabled version is not itself if (currentVersion != null && !currentVersion.equals(appName)) { @@ -279,12 +269,11 @@ public String getVersionFromSameDir(File dir) throws VersioningSyntaxException{ try { - Iterator it = domain.getApplications().getApplications().iterator(); Application app = null; // check if directory deployment exist - while ( it.hasNext() ) { - app = (Application) it.next(); + for (Application element : domain.getApplications().getApplications()) { + app = element; /* * A lifecycle module appears as an application but has a null location. */ diff --git a/nucleus/deployment/common/src/main/java/org/glassfish/deployment/versioning/VersioningUtils.java b/nucleus/deployment/common/src/main/java/org/glassfish/deployment/versioning/VersioningUtils.java index 988d9e35e58..1ee8d3b5da9 100644 --- a/nucleus/deployment/common/src/main/java/org/glassfish/deployment/versioning/VersioningUtils.java +++ b/nucleus/deployment/common/src/main/java/org/glassfish/deployment/versioning/VersioningUtils.java @@ -1,4 +1,5 @@ /* + * Copyright (c) 2022 Contributors to the Eclipse Foundation * Copyright (c) 2008, 2018 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the @@ -17,10 +18,9 @@ package org.glassfish.deployment.versioning; import com.sun.enterprise.config.serverbeans.Application; -import com.sun.enterprise.util.LocalStringManagerImpl; +import java.text.MessageFormat; import java.util.ArrayList; import java.util.Collections; -import java.util.Iterator; import java.util.List; import java.util.StringTokenizer; @@ -30,11 +30,8 @@ * * @author Romain GRECOURT - SERLI (romain.grecourt@serli.com) */ - public class VersioningUtils { - public static final LocalStringManagerImpl LOCALSTRINGS = - new LocalStringManagerImpl(VersioningUtils.class); public static final String EXPRESSION_SEPARATOR = ":"; public static final String EXPRESSION_WILDCARD = "*"; public static final String REPOSITORY_DASH = "~"; @@ -64,13 +61,13 @@ public static final String getUntaggedName(String appName) if (colonIndex == 0) { // if appName is starting with a colon throw new VersioningSyntaxException( - LOCALSTRINGS.getLocalString("versioning.deployment.invalid.appname1", + MessageFormat.format( "excepted application name before colon: {0}", appName)); } else if (colonIndex == (appName.length() - 1)) { // if appName is ending with a colon throw new VersioningSyntaxException( - LOCALSTRINGS.getLocalString("versioning.deployment.invalid.appname2", + MessageFormat.format( "excepted version identifier after colon: {0}", appName)); } @@ -104,13 +101,13 @@ public static final String getExpression(String appName) if (colonIndex == 0) { // if appName is starting with a colon throw new VersioningSyntaxException( - LOCALSTRINGS.getLocalString("versioning.deployment.invalid.appname1", + MessageFormat.format( "excepted application name before colon: {0}", appName)); } else if (colonIndex == (appName.length() - 1)) { // if appName is ending with a colon throw new VersioningSyntaxException( - LOCALSTRINGS.getLocalString("versioning.deployment.invalid.appname2", + MessageFormat.format( "excepted version identifier after colon: {0}", appName)); } @@ -139,9 +136,7 @@ public static final void checkIdentifier(String appName) String identifier = getExpression(appName); if (identifier != null && identifier.contains(EXPRESSION_WILDCARD)) { - throw new VersioningWildcardException( - LOCALSTRINGS.getLocalString("versioning.deployment.wildcard.not.allowed", - "Wildcard character(s) are not allowed in a version identifier.")); + throw new VersioningWildcardException("Wildcard character(s) are not allowed in a version identifier."); } } @@ -158,12 +153,8 @@ public static final void checkIdentifier(String appName) public static final List getVersions(String untaggedName, List allApplications) { - List allVersions = new ArrayList(); - Iterator it = allApplications.iterator(); - - while (it.hasNext()) { - Application app = it.next(); - + List allVersions = new ArrayList<>(); + for (Application app : allApplications) { // if a tagged version or untagged version of the app if (app.getName().startsWith(untaggedName + EXPRESSION_SEPARATOR) || app.getName().equals(untaggedName)) { @@ -198,10 +189,7 @@ public static final List matchExpression(List listVersion, Strin return listVersion.subList(listVersion.indexOf(appName), listVersion.indexOf(appName) + 1); } else { - throw new VersioningException( - LOCALSTRINGS.getLocalString("versioning.deployment.version.notreg", - "version {0} not registered", - appName)); + throw new VersioningException(MessageFormat.format("version {0} not registered", appName)); } } @@ -212,24 +200,18 @@ public static final List matchExpression(List listVersion, Strin return listVersion.subList(listVersion.indexOf(appName), listVersion.indexOf(appName) + 1); } else { - throw new VersioningException( - LOCALSTRINGS.getLocalString("versioning.deployment.version.notreg", - "Version {0} not registered", - appName)); + throw new VersioningException(MessageFormat.format("Version {0} not registered", appName)); } } StringTokenizer st = new StringTokenizer(expressionVersion, EXPRESSION_WILDCARD); String lastToken = null; - List matchedVersions = new ArrayList(listVersion); + List matchedVersions = new ArrayList<>(listVersion); while (st.hasMoreTokens()) { String token = st.nextToken(); - Iterator it = listVersion.iterator(); - - while (it.hasNext()) { - String app = (String) it.next(); + for (String app : listVersion) { String identifier = getExpression(app); // get the position of the last token in the current identifier diff --git a/nucleus/deployment/common/src/test/java/com/sun/enterprise/deployment/deploy/shared/InputJarArchiveTest.java b/nucleus/deployment/common/src/test/java/com/sun/enterprise/deployment/deploy/shared/InputJarArchiveTest.java index e7feb0f69a3..ab16caec611 100644 --- a/nucleus/deployment/common/src/test/java/com/sun/enterprise/deployment/deploy/shared/InputJarArchiveTest.java +++ b/nucleus/deployment/common/src/test/java/com/sun/enterprise/deployment/deploy/shared/InputJarArchiveTest.java @@ -1,6 +1,6 @@ /* + * Copyright (c) 2021, 2022 Contributors to the Eclipse Foundation * Copyright (c) 2009, 2018 Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2021 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 @@ -72,7 +72,7 @@ public void testCollectionWrappedEnumerationInitialSize() { @Test public void testCollectionWrappedEnumerationMiddleSize() { - CollectionWrappedEnumeration cwe = new CollectionWrappedEnumeration<>(() -> testEnum()); + CollectionWrappedEnumeration cwe = new CollectionWrappedEnumeration<>(InputJarArchiveTest::testEnum); ArrayList answer = new ArrayList<>(); Iterator it = cwe.iterator(); answer.add(it.next()); @@ -86,7 +86,7 @@ public void testCollectionWrappedEnumerationMiddleSize() { @Test public void testCollectionWrappedEnumerationEndSize() { - CollectionWrappedEnumeration cwe = new CollectionWrappedEnumeration<>(() -> testEnum()); + CollectionWrappedEnumeration cwe = new CollectionWrappedEnumeration<>(InputJarArchiveTest::testEnum); List answer = new ArrayList<>(); Iterator it = cwe.iterator(); answer.add(it.next()); @@ -101,9 +101,7 @@ public void testCollectionWrappedEnumerationEndSize() { private ReadableArchive getArchiveForTest() throws IOException { File tempJAR = createTestJAR(); - final InputJarArchive arch = new InputJarArchive(); - arch.open(tempJAR.toURI()); - return arch; + return new InputJarArchive(tempJAR); } private void retireArchive(final ReadableArchive arch) throws IOException { diff --git a/nucleus/osgi-platforms/osgi-container/src/main/java/org/glassfish/extras/osgicontainer/OSGiArchiveHandler.java b/nucleus/osgi-platforms/osgi-container/src/main/java/org/glassfish/extras/osgicontainer/OSGiArchiveHandler.java index e10c1acee50..5369e6181ec 100644 --- a/nucleus/osgi-platforms/osgi-container/src/main/java/org/glassfish/extras/osgicontainer/OSGiArchiveHandler.java +++ b/nucleus/osgi-platforms/osgi-container/src/main/java/org/glassfish/extras/osgicontainer/OSGiArchiveHandler.java @@ -222,7 +222,6 @@ private void expandJar(JarInputStream jis, WritableArchive target) throws IOExce logger.logp(Level.FINER, "OSGiArchiveHandler", "expandJar", "Writing jar entry name = {0}, size = {1}", new Object[] {entryName, entrySize}); try (WritableArchiveEntry os = target.putNextEntry(entryName)) { - // passing 0 will force it to read until EOS FileUtils.copy(jis, os); } } finally { From f6a14a9a7a298a1918ac2c7ec1c8011955dcee5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Mat=C4=9Bj=C4=8Dek?= Date: Fri, 2 Dec 2022 12:29:51 +0100 Subject: [PATCH 03/12] Try-with MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: David Matějček --- .../admin/cli/embeddable/DeployerImpl.java | 97 ++++++------------- .../admin/remote/RemoteAdminCommand.java | 28 +++--- .../admin/payload/PayloadFilesManager.java | 12 +-- .../glassfish/admin/payload/PayloadImpl.java | 65 ++++++------- .../admin/payload/ZipPayloadImpl.java | 15 +-- .../java/org/glassfish/api/admin/Payload.java | 10 +- .../enterprise/v3/admin/CheckpointHelper.java | 14 +-- 7 files changed, 94 insertions(+), 147 deletions(-) diff --git a/nucleus/admin/cli/src/main/java/com/sun/enterprise/admin/cli/embeddable/DeployerImpl.java b/nucleus/admin/cli/src/main/java/com/sun/enterprise/admin/cli/embeddable/DeployerImpl.java index 1027ca00432..9a0cc9ece63 100644 --- a/nucleus/admin/cli/src/main/java/com/sun/enterprise/admin/cli/embeddable/DeployerImpl.java +++ b/nucleus/admin/cli/src/main/java/com/sun/enterprise/admin/cli/embeddable/DeployerImpl.java @@ -1,4 +1,5 @@ /* + * Copyright (c) 2022 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 @@ -16,21 +17,10 @@ package com.sun.enterprise.admin.cli.embeddable; -import org.glassfish.admin.payload.PayloadFilesManager; -import org.glassfish.admin.payload.PayloadImpl; -import org.glassfish.api.ActionReport; -import org.glassfish.api.admin.CommandException; -import org.glassfish.api.admin.ParameterMap; -import org.glassfish.api.admin.Payload; -import org.glassfish.embeddable.Deployer; -import org.glassfish.embeddable.GlassFishException; -import org.jvnet.hk2.annotations.ContractsProvided; - -import org.jvnet.hk2.annotations.Service; -import org.glassfish.hk2.api.PerLookup; -import org.glassfish.hk2.api.ServiceLocator; +import com.sun.enterprise.util.io.FileUtils; import jakarta.inject.Inject; + import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; @@ -38,14 +28,26 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; -import java.io.OutputStream; import java.net.URI; import java.util.ArrayList; import java.util.Collection; import java.util.Properties; import java.util.logging.Level; import java.util.logging.Logger; + +import org.glassfish.admin.payload.PayloadFilesManager; +import org.glassfish.admin.payload.PayloadImpl; +import org.glassfish.api.ActionReport; +import org.glassfish.api.admin.CommandException; +import org.glassfish.api.admin.ParameterMap; +import org.glassfish.api.admin.Payload; +import org.glassfish.embeddable.Deployer; +import org.glassfish.embeddable.GlassFishException; +import org.glassfish.hk2.api.PerLookup; +import org.glassfish.hk2.api.ServiceLocator; import org.glassfish.internal.api.InternalSystemAdministrator; +import org.jvnet.hk2.annotations.ContractsProvided; +import org.jvnet.hk2.annotations.Service; /** * This is an implementation of {@link Deployer}. Unlike the other EmbeddedDeployer, this deployer uses admin command @@ -148,7 +150,7 @@ public Collection getDeployedApplications() throws GlassFishException { CommandExecutorImpl executer = habitat.getService(CommandExecutorImpl.class); ActionReport report = executer.executeCommand("list-components"); Properties props = report.getTopMessagePart().getProps(); - return new ArrayList(props.stringPropertyNames()); + return new ArrayList<>(props.stringPropertyNames()); } catch (Exception e) { throw new GlassFishException(e); } @@ -168,37 +170,16 @@ private File createFile(InputStream in) throws IOException { File file; file = File.createTempFile("app", "tmp"); file.deleteOnExit(); - OutputStream out = null; - try { - out = new FileOutputStream(file); - copyStream(in, out); + try (FileOutputStream out = new FileOutputStream(file)) { + FileUtils.copy(in, out); } finally { if (in != null) { - try { - in.close(); - } catch (IOException e) { - // ignore - } - } - if (out != null) { - try { - out.close(); - } finally { - // ignore - } + in.close(); } } return file; } - private void copyStream(InputStream in, OutputStream out) throws IOException { - byte[] buf = new byte[4096]; - int len; - while ((len = in.read(buf)) >= 0) { - out.write(buf, 0, len); - } - } - /** * Extract the payload (client side stub jar files) to the directory specified via --retrieve option. * @@ -208,8 +189,6 @@ private void copyStream(InputStream in, OutputStream out) throws IOException { */ private void extractPayload(Payload.Outbound outboundPayload, ActionReport actionReport, File retrieveDir) { File payloadZip = null; - FileOutputStream payloadOutputStream = null; - FileInputStream payloadInputStream = null; try { /* * Add the report to the payload to mimic what the normal @@ -228,41 +207,25 @@ private void extractPayload(Payload.Outbound outboundPayload, ActionReport actio * then reading from that file. */ payloadZip = File.createTempFile("appclient", ".zip"); - payloadOutputStream = new FileOutputStream(payloadZip); - outboundPayload.writeTo(payloadOutputStream); - payloadOutputStream.flush(); - payloadOutputStream.close(); - + try (FileOutputStream payloadOutputStream = new FileOutputStream(payloadZip)) { + outboundPayload.writeTo(payloadOutputStream); + } /* * Use the temp file's contents as the inbound payload to * correctly process the downloaded files. */ - final PayloadFilesManager pfm = new PayloadFilesManager.Perm(retrieveDir, - null /* no action report to record extraction results */, logger); - payloadInputStream = new FileInputStream(payloadZip); - final PayloadImpl.Inbound inboundPayload = PayloadImpl.Inbound.newInstance("application/zip", payloadInputStream); - pfm.processParts(inboundPayload); // explodes the payloadZip. + final PayloadFilesManager pfm = new PayloadFilesManager.Perm(retrieveDir, null, logger); + try (FileInputStream payloadInputStream = new FileInputStream(payloadZip)) { + PayloadImpl.Inbound inboundPayload = PayloadImpl.Inbound.newInstance("application/zip", payloadInputStream); + pfm.processParts(inboundPayload); // explodes the payloadZip. + } } catch (Exception ex) { // Log error and ignore exception. logger.log(Level.WARNING, ex.getMessage(), ex); } finally { - if (payloadOutputStream != null) { - try { - payloadOutputStream.close(); - } catch (IOException ioex) { - logger.warning(ioex.getMessage()); - } - } - if (payloadInputStream != null) { - try { - payloadInputStream.close(); - } catch (IOException ioex) { - logger.warning(ioex.getMessage()); - } - } if (payloadZip != null) { - if (payloadZip.delete() == false) { - logger.log(Level.WARNING, "Cannot delete payload: {0}", payloadZip.toString()); + if (!payloadZip.delete()) { + logger.log(Level.WARNING, "Cannot delete payload: {0}", payloadZip); } } } diff --git a/nucleus/admin/util/src/main/java/com/sun/enterprise/admin/remote/RemoteAdminCommand.java b/nucleus/admin/util/src/main/java/com/sun/enterprise/admin/remote/RemoteAdminCommand.java index fc7a5819863..a97cd0668ec 100644 --- a/nucleus/admin/util/src/main/java/com/sun/enterprise/admin/remote/RemoteAdminCommand.java +++ b/nucleus/admin/util/src/main/java/com/sun/enterprise/admin/remote/RemoteAdminCommand.java @@ -67,6 +67,7 @@ import org.glassfish.admin.payload.PayloadFilesManager; import org.glassfish.admin.payload.PayloadImpl; +import org.glassfish.admin.payload.PayloadImpl.Inbound; import org.glassfish.api.admin.AuthenticationException; import org.glassfish.api.admin.CommandException; import org.glassfish.api.admin.CommandModel; @@ -1111,17 +1112,13 @@ public void prepareConnection(HttpURLConnection urlConnection) { @Override public void useConnection(HttpURLConnection urlConnection) throws CommandException, IOException { - - Payload.Inbound inboundPayload; - try (InputStream in = urlConnection.getInputStream()) { - String responseContentType = urlConnection.getContentType(); - logger.finer("Response Content-Type: " + responseContentType); - inboundPayload = PayloadImpl.Inbound.newInstance(responseContentType, in); - if (inboundPayload == null) { - throw new IOException(strings.get("NoPayloadSupport", responseContentType)); - } + InputStream in = urlConnection.getInputStream(); + String responseContentType = urlConnection.getContentType(); + logger.finer("Response Content-Type: " + responseContentType); + Inbound inboundPayload = PayloadImpl.Inbound.newInstance(responseContentType, in); + if (inboundPayload == null) { + throw new IOException(strings.get("NoPayloadSupport", responseContentType)); } - boolean isReportProcessed = false; Iterator partIt = inboundPayload.parts(); while (partIt.hasNext()) { @@ -1129,18 +1126,17 @@ public void useConnection(HttpURLConnection urlConnection) throws CommandExcepti * There should be only one part, which should be the * metadata, but skip any other parts just in case. */ - if (!isReportProcessed) { + if (isReportProcessed) { + partIt.next(); // just throw it away + } else { metadataErrors = new StringBuilder(); - try (InputStream inputStream = partIt.next().getInputStream()) { - commandModel = parseMetadata(inputStream, metadataErrors); - } + commandModel = parseMetadata(partIt.next().getInputStream(), metadataErrors); logger.finer("fetchCommandModel: got command opts: " + commandModel); isReportProcessed = true; - } else { - partIt.next(); // just throw it away } } } + }); if (commandModel == null) { if (metadataErrors == null) { diff --git a/nucleus/common/common-util/src/main/java/org/glassfish/admin/payload/PayloadFilesManager.java b/nucleus/common/common-util/src/main/java/org/glassfish/admin/payload/PayloadFilesManager.java index f725121ef1e..be4a9ed2483 100644 --- a/nucleus/common/common-util/src/main/java/org/glassfish/admin/payload/PayloadFilesManager.java +++ b/nucleus/common/common-util/src/main/java/org/glassfish/admin/payload/PayloadFilesManager.java @@ -374,19 +374,15 @@ private File replaceFile(final Payload.Part part) throws IOException { private void consumePartBody(final Part part) throws FileNotFoundException, IOException { try (InputStream is = part.getInputStream()) { - byte[] buffer = new byte[1024 * 64]; - while (is.read(buffer) != -1) { - } + is.readAllBytes(); } } private void processReport(final Payload.Part part) throws Exception { - if (reportHandler != null) { - try (InputStream inputStream = part.getInputStream()) { - reportHandler.handleReport(inputStream); - } - } else { + if (reportHandler == null) { consumePartBody(part); + } else { + reportHandler.handleReport(part.getInputStream()); } } diff --git a/nucleus/common/common-util/src/main/java/org/glassfish/admin/payload/PayloadImpl.java b/nucleus/common/common-util/src/main/java/org/glassfish/admin/payload/PayloadImpl.java index b38a329ae3a..8aca45c939a 100644 --- a/nucleus/common/common-util/src/main/java/org/glassfish/admin/payload/PayloadImpl.java +++ b/nucleus/common/common-util/src/main/java/org/glassfish/admin/payload/PayloadImpl.java @@ -17,6 +17,8 @@ package org.glassfish.admin.payload; +import com.sun.enterprise.util.io.FileUtils; + import java.io.*; import java.net.URI; import java.net.URLConnection; @@ -37,7 +39,7 @@ public abstract static class Outbound implements Payload.Outbound { /** * Partial implementation of the Outbound Payload. */ - private final ArrayList parts = new ArrayList(); + private final ArrayList parts = new ArrayList<>(); private boolean dirty = false; @@ -125,8 +127,7 @@ public void attachFile( enhancedProps.setProperty("data-request-type", "file-xfer"); enhancedProps.setProperty("data-request-name", dataRequestName); enhancedProps.setProperty("data-request-is-recursive", Boolean.toString(isRecursive)); - enhancedProps.setProperty("last-modified", Long.toString(file.lastModified()) - ); + enhancedProps.setProperty("last-modified", Long.toString(file.lastModified())); if (file.isDirectory() && isRecursive) { String relativeURIPath = fileURI.getRawPath(); @@ -370,23 +371,27 @@ public String getHeaderName() { @Override public String getContentType() { - return (isComplex()) ? getComplexContentType() : getSinglePartContentType(); + return isComplex() ? getComplexContentType() : getSinglePartContentType(); } public ArrayList getParts() { return parts; } + /** * Writes the Parts in this Outbound Payload to the specified output - * stream; concrete implementations will implement this abstract method. + * stream and closes it. + *

+ * Concrete implementations will implement this abstract method. + * * @param os the OutputStream to which the Parts should be written * @throws java.io.IOException */ protected abstract void writePartsTo(final OutputStream os) throws IOException; /** - * Writes the Payload to the specified output stream. + * Writes the Payload to the specified output stream and closes it. * * @param os the OutputStream to which the Payload should be written * @throws java.io.IOException @@ -508,10 +513,10 @@ public Iterator parts() { * Partial implementation of Part. */ public static abstract class Part implements Payload.Part { - private String name; - private String contentType; - private Properties props; - private boolean isRecursive; + private final String name; + private final String contentType; + private final Properties props; + private final boolean isRecursive; private File extractedFile; /** @@ -531,7 +536,7 @@ public static abstract class Part implements Payload.Part { if (props != null) { this.props.putAll(props); } - isRecursive = Boolean.valueOf(this.props.getProperty("data-request-is-recursive")); + isRecursive = Boolean.parseBoolean(this.props.getProperty("data-request-is-recursive")); } @Override @@ -571,13 +576,12 @@ public File getExtracted() { protected InputStream getExtractedInputStream() { File file = getExtracted(); - if (file != null) { - try { - return new FileInputStream(file); - } catch (FileNotFoundException ex) { - return null; - } - } else { + if (file == null) { + return null; + } + try { + return new FileInputStream(file); + } catch (FileNotFoundException ex) { return null; } } @@ -670,13 +674,8 @@ static class Streamed extends PayloadImpl.Part { @Override public InputStream getInputStream() { InputStream extrIS = getExtractedInputStream(); - if (extrIS == null) { - return is; - } else { - return extrIS; - } + return extrIS == null ? is : extrIS; } - } /** @@ -684,7 +683,7 @@ public InputStream getInputStream() { */ static class Buffered extends PayloadImpl.Part { private final String content; - private InputStream is = null; + private ByteArrayInputStream is = null; /** * Creates a new buffer-based Part. @@ -704,13 +703,10 @@ static class Buffered extends PayloadImpl.Part { } @Override - public InputStream getInputStream() { + public ByteArrayInputStream getInputStream() { if (is == null) { - /* - * Some parts might not have content. - */ - final byte[] data = (content != null) ? - content.getBytes() : new byte[0]; + // Some parts might not have content. + final byte[] data = content == null ? new byte[0] : content.getBytes(); is = new ByteArrayInputStream(data); } return is; @@ -745,11 +741,8 @@ static class Filed extends PayloadImpl.Part { @Override public InputStream getInputStream() { try { - return (file != null - ? new SelfClosingInputStream( - new BufferedInputStream( - new FileInputStream(file))) - : dummyStream()); + return file == null ? dummyStream() + : new SelfClosingInputStream(new BufferedInputStream(new FileInputStream(file))); } catch (FileNotFoundException ex) { /* * Silently return null; validateFile has already logged a message diff --git a/nucleus/common/common-util/src/main/java/org/glassfish/admin/payload/ZipPayloadImpl.java b/nucleus/common/common-util/src/main/java/org/glassfish/admin/payload/ZipPayloadImpl.java index 7bfc7cda808..48261795422 100644 --- a/nucleus/common/common-util/src/main/java/org/glassfish/admin/payload/ZipPayloadImpl.java +++ b/nucleus/common/common-util/src/main/java/org/glassfish/admin/payload/ZipPayloadImpl.java @@ -72,13 +72,13 @@ private void prepareEntry(final Payload.Part part, final ZipOutputStream zos) th @Override public void writePartsTo(OutputStream os) throws IOException { - ZipOutputStream zos = new ZipOutputStream(os); - for (Payload.Part part : getParts()) { - prepareEntry(part, zos); - part.copy(zos); - zos.closeEntry(); + try (ZipOutputStream zos = new ZipOutputStream(os)) { + for (Payload.Part part : getParts()) { + prepareEntry(part, zos); + part.copy(zos); + zos.closeEntry(); + } } - zos.close(); } private Outbound() { @@ -243,7 +243,7 @@ public static boolean supportsContentType(final String contentType) { @Override public Iterator parts() { - return new Iterator() { + return new Iterator<>() { @Override public boolean hasNext() { @@ -293,6 +293,7 @@ private Part( this.inboundPayload = inboundPayload; } + @Override public InputStream getInputStream() { return new Inbound.ZipEntryInputStream(inboundPayload); diff --git a/nucleus/common/glassfish-api/src/main/java/org/glassfish/api/admin/Payload.java b/nucleus/common/glassfish-api/src/main/java/org/glassfish/api/admin/Payload.java index c99f13a0bf3..5cdfd71e9cc 100644 --- a/nucleus/common/glassfish-api/src/main/java/org/glassfish/api/admin/Payload.java +++ b/nucleus/common/glassfish-api/src/main/java/org/glassfish/api/admin/Payload.java @@ -322,14 +322,14 @@ public interface Part { Properties getProperties(); /** - * Returns an InputStream suitable for reading the content of the Part. - * - * @return + * @return an InputStream suitable for reading the content of the Part. + * Caller is responsible for closing. */ InputStream getInputStream(); /** * Copies the contents of the Part to the specified OutputStream. + * Doesn't close the stream. * * @param os target OutputStream to receive the content of the Part * @throws java.io.IOException @@ -337,9 +337,7 @@ public interface Part { void copy(final OutputStream os) throws IOException; /** - * Indicates if the Part represents a recursive action or not. - * - * @return + * @return true indicates if the Part represents a recursive action */ boolean isRecursive(); diff --git a/nucleus/core/kernel/src/main/java/com/sun/enterprise/v3/admin/CheckpointHelper.java b/nucleus/core/kernel/src/main/java/com/sun/enterprise/v3/admin/CheckpointHelper.java index 7ab02bac22e..cd8a5b5a5d5 100644 --- a/nucleus/core/kernel/src/main/java/com/sun/enterprise/v3/admin/CheckpointHelper.java +++ b/nucleus/core/kernel/src/main/java/com/sun/enterprise/v3/admin/CheckpointHelper.java @@ -400,14 +400,14 @@ private Inbound loadInbound(File inboundFile) throws IOException { // ZipPayloadImpl private void writePartsTo(Iterator parts, OutputStream os) throws IOException { - ZipOutputStream zos = new ZipOutputStream(os); - while (parts.hasNext()) { - Part part = parts.next(); - prepareEntry(part, zos); - part.copy(zos); - zos.closeEntry(); + try (ZipOutputStream zos = new ZipOutputStream(os)) { + while (parts.hasNext()) { + Part part = parts.next(); + prepareEntry(part, zos); + part.copy(zos); + zos.closeEntry(); + } } - zos.close(); } private void prepareEntry(final Payload.Part part, final ZipOutputStream zos) throws IOException { From 73bbe703009579be5e8d923ef79eeee81bd1bfee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Mat=C4=9Bj=C4=8Dek?= Date: Tue, 20 Feb 2024 18:12:17 +0100 Subject: [PATCH 04/12] Updated to pass the build after the rebase. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: David Matějček # Conflicts: # appserver/tests/testcontainers/pom.xml # appserver/tests/testcontainers/src/test/java/org/glassfish/main/test/tc/DomainRestartITest.java # appserver/tests/testcontainers/src/test/java/org/glassfish/main/test/tc/GlassFishContainer.java --- .../appclient/client/acc/ACCClassLoader.java | 2 +- .../glassfish/web/loader/JarFileManager.java | 6 ++---- .../com/sun/enterprise/util/io/FileUtils.java | 18 ++++++++++++------ 3 files changed, 15 insertions(+), 11 deletions(-) diff --git a/appserver/appclient/client/acc/src/main/java/org/glassfish/appclient/client/acc/ACCClassLoader.java b/appserver/appclient/client/acc/src/main/java/org/glassfish/appclient/client/acc/ACCClassLoader.java index 21f949c5dae..72031f4f5c7 100644 --- a/appserver/appclient/client/acc/src/main/java/org/glassfish/appclient/client/acc/ACCClassLoader.java +++ b/appserver/appclient/client/acc/src/main/java/org/glassfish/appclient/client/acc/ACCClassLoader.java @@ -186,7 +186,7 @@ private byte[] readByteCode(final String className) throws ClassNotFoundExceptio throw new ClassNotFoundException(className); } ByteArrayOutputStream baos = new ByteArrayOutputStream(); - FileUtils.copy(is, baos, is.available()); + FileUtils.copy(is, baos); return baos.toByteArray(); } catch (IOException e) { throw new ClassNotFoundException(className, e); diff --git a/appserver/web/war-util/src/main/java/org/glassfish/web/loader/JarFileManager.java b/appserver/web/war-util/src/main/java/org/glassfish/web/loader/JarFileManager.java index 523aaf0a8e6..9afb1a9db80 100644 --- a/appserver/web/war-util/src/main/java/org/glassfish/web/loader/JarFileManager.java +++ b/appserver/web/war-util/src/main/java/org/glassfish/web/loader/JarFileManager.java @@ -20,7 +20,6 @@ import java.io.Closeable; import java.io.File; -import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.lang.System.Logger; @@ -292,9 +291,8 @@ private static void extractResource(JarFile jarFile, File loaderDir, String path LOG.log(WARNING, UNABLE_TO_CREATE, resourceFile.getParentFile()); } - try (InputStream is = jarFile.getInputStream(jarEntry); - FileOutputStream os = new FileOutputStream(resourceFile)) { - FileUtils.copy(is, os, Long.MAX_VALUE); + try (InputStream is = jarFile.getInputStream(jarEntry)) { + FileUtils.copy(is, resourceFile, jarEntry.getSize()); } catch (IOException e) { LOG.log(WARNING, "Failed to copy entry " + jarEntry, e); } diff --git a/nucleus/common/common-util/src/main/java/com/sun/enterprise/util/io/FileUtils.java b/nucleus/common/common-util/src/main/java/com/sun/enterprise/util/io/FileUtils.java index 5af6ec5c685..bddf7d021d5 100644 --- a/nucleus/common/common-util/src/main/java/com/sun/enterprise/util/io/FileUtils.java +++ b/nucleus/common/common-util/src/main/java/com/sun/enterprise/util/io/FileUtils.java @@ -742,16 +742,22 @@ static boolean isValidString(String s) { /** - * @param in It will be closed after processing, doesn't need to be buffered as this method uses - * own 8K buffer. + * FIXME: Document and write test with large zip file to see if it wouldn't be better to use + * BufferedInputStream and BufferedOutputStream. + * FIXME: Usually used with JarFile and it's entry. Add API. + *

+ * WARNING: Don't use it when you don't know the byteCount value. + * + * @param in It will be closed after processing. * @param out Target output file. - * @param bytes Maximal count of bytes to be transferred + * @param byteCount count of bytes to be transferred. * @throws IOException */ - public static void copy(InputStream in, File out, long bytes) throws IOException { - try (ReadableByteChannel inputChannel = Channels.newChannel(in); + public static void copy(InputStream in, File out, long byteCount) throws IOException { + try ( + ReadableByteChannel inputChannel = Channels.newChannel(in); FileOutputStream output = new FileOutputStream(out)) { - output.getChannel().transferFrom(inputChannel, 0, bytes); + output.getChannel().transferFrom(inputChannel, 0, byteCount); } } From 5db076fe7175053289ad95a19362d65ddd00c79f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Mat=C4=9Bj=C4=8Dek?= Date: Tue, 20 Feb 2024 18:13:59 +0100 Subject: [PATCH 05/12] Rebase to eclipse/master MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: David Matějček # Conflicts: # appserver/tests/testcontainers/pom.xml # appserver/tests/testcontainers/src/test/java/org/glassfish/main/test/tc/GlassFishContainer.java --- .../main/admin/test/rest/RestTestBase.java | 6 +++--- appserver/tests/jakartaee/pom.xml | 17 ----------------- .../sun/enterprise/loader/ASURLClassLoader.java | 4 ++-- .../com/sun/enterprise/util/CULoggerInfo.java | 7 ------- 4 files changed, 5 insertions(+), 29 deletions(-) delete mode 100644 appserver/tests/jakartaee/pom.xml diff --git a/appserver/tests/admin/tests/src/test/java/org/glassfish/main/admin/test/rest/RestTestBase.java b/appserver/tests/admin/tests/src/test/java/org/glassfish/main/admin/test/rest/RestTestBase.java index 6e013fefa63..4655c196348 100644 --- a/appserver/tests/admin/tests/src/test/java/org/glassfish/main/admin/test/rest/RestTestBase.java +++ b/appserver/tests/admin/tests/src/test/java/org/glassfish/main/admin/test/rest/RestTestBase.java @@ -17,12 +17,13 @@ package org.glassfish.main.admin.test.rest; +import com.sun.enterprise.util.io.FileUtils; + import jakarta.ws.rs.client.Client; import jakarta.ws.rs.core.MultivaluedMap; import jakarta.ws.rs.core.Response; import java.io.File; -import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; @@ -45,7 +46,6 @@ import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.TestInfo; -import static com.sun.enterprise.util.io.FileUtils.copy; import static com.sun.enterprise.util.io.FileUtils.ensureWritableDir; import static jakarta.ws.rs.core.MediaType.TEXT_PLAIN; import static org.glassfish.main.itest.tools.GlassFishTestEnvironment.getTargetDirectory; @@ -95,7 +95,7 @@ public static void captureLogAndCloseClient(final TestInfo testInfo) throws Exce ensureWritableDir(reportDir); File reportFile = new File(reportDir, testInfo.getTestClass().orElseThrow().getName() + "-server.log"); - copy(response.readEntity(InputStream.class), new FileOutputStream(reportFile), Long.MAX_VALUE); + FileUtils.copy(response.readEntity(InputStream.class), reportFile, Long.MAX_VALUE); } } diff --git a/appserver/tests/jakartaee/pom.xml b/appserver/tests/jakartaee/pom.xml deleted file mode 100644 index 128c48790e4..00000000000 --- a/appserver/tests/jakartaee/pom.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - 4.0.0 - - org.glassfish.main.tests - tests - 7.0.13-SNAPSHOT - - org.glassfish.main.tests.jakartaee - jakartaee - GlassFish Additional Jakarta EE Tests - Tests that cover functionality not covered by the Jakarta EE TCK (yet). These tests should complement TCK tests and they could be donated to the TCK later. - pom - - concurrency - - \ No newline at end of file diff --git a/nucleus/common/common-util/src/main/java/com/sun/enterprise/loader/ASURLClassLoader.java b/nucleus/common/common-util/src/main/java/com/sun/enterprise/loader/ASURLClassLoader.java index 0d48056fe87..3630f39725a 100644 --- a/nucleus/common/common-util/src/main/java/com/sun/enterprise/loader/ASURLClassLoader.java +++ b/nucleus/common/common-util/src/main/java/com/sun/enterprise/loader/ASURLClassLoader.java @@ -153,8 +153,8 @@ public boolean isClosed() { public void preDestroy() { try { close(); - } catch(IOException ioe) { - _logger.log(INFO, CULoggerInfo.getString(CULoggerInfo.exceptionIO), ioe); + } catch (IOException ioe) { + _logger.log(Level.SEVERE, "Could not close the classloader " + this, ioe); } } diff --git a/nucleus/common/common-util/src/main/java/com/sun/enterprise/util/CULoggerInfo.java b/nucleus/common/common-util/src/main/java/com/sun/enterprise/util/CULoggerInfo.java index 565f67cd7fa..1bad0783ddc 100644 --- a/nucleus/common/common-util/src/main/java/com/sun/enterprise/util/CULoggerInfo.java +++ b/nucleus/common/common-util/src/main/java/com/sun/enterprise/util/CULoggerInfo.java @@ -54,13 +54,6 @@ public static String getString(String key, Object... args) { return MessageFormat.format(getString(key), args); } - @LogMessageInfo( - message = "Some IOException occurred", - cause = "An unexpected exception occurred.", - action = "Check the system logs and contact Oracle support.", - level = "SEVERE") - public static final String exceptionIO = LOGMSG_PREFIX + "-00031"; - @LogMessageInfo( message = "Failed to process class {0} with bytecode preprocessor {1}", cause = "Unknown", From 6595491b2f8b34c1d730ec669d794306b179fe79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Mat=C4=9Bj=C4=8Dek?= Date: Sun, 1 Oct 2023 17:13:08 +0200 Subject: [PATCH 06/12] Removed unused constant I18N MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: David Matějček --- .../src/main/java/com/sun/enterprise/util/io/FileUtils.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/nucleus/common/common-util/src/main/java/com/sun/enterprise/util/io/FileUtils.java b/nucleus/common/common-util/src/main/java/com/sun/enterprise/util/io/FileUtils.java index bddf7d021d5..d44703cbe29 100644 --- a/nucleus/common/common-util/src/main/java/com/sun/enterprise/util/io/FileUtils.java +++ b/nucleus/common/common-util/src/main/java/com/sun/enterprise/util/io/FileUtils.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Contributors to the Eclipse Foundation + * Copyright (c) 2022, 2023 Contributors to the Eclipse Foundation * Copyright (c) 2006, 2018 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the @@ -17,7 +17,6 @@ package com.sun.enterprise.util.io; -import com.sun.enterprise.universal.i18n.LocalStringsImpl; import com.sun.enterprise.util.OS; import java.io.BufferedInputStream; @@ -59,7 +58,6 @@ public final class FileUtils { public static final File USER_HOME = new File(System.getProperty("user.home")); private static final Logger LOG = System.getLogger(FileUtils.class.getName()); - private static final LocalStringsImpl I18N = new LocalStringsImpl(FileUtils.class); private static final char[] ILLEGAL_FILENAME_CHARS = {'/', '\\', ':', '*', '?', '"', '<', '>', '|'}; private static final char REPLACEMENT_CHAR = '_'; From e426d265fe413987f61df8a55d4b1d546970e361 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Mat=C4=9Bj=C4=8Dek?= Date: Fri, 6 Oct 2023 19:45:12 +0200 Subject: [PATCH 07/12] Removed hacks for unknown size of the input stream MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: David Matějček --- .../main/admin/test/rest/RestTestBase.java | 4 +- .../com/sun/enterprise/util/io/FileUtils.java | 34 +++++++--- .../admin/payload/PayloadFilesManager.java | 2 +- .../glassfish/admin/payload/PayloadImpl.java | 12 +++- .../sun/enterprise/util/io/FileUtilsTest.java | 62 +++++++++++++------ .../enterprise/v3/admin/CheckpointHelper.java | 2 +- 6 files changed, 85 insertions(+), 31 deletions(-) diff --git a/appserver/tests/admin/tests/src/test/java/org/glassfish/main/admin/test/rest/RestTestBase.java b/appserver/tests/admin/tests/src/test/java/org/glassfish/main/admin/test/rest/RestTestBase.java index 4655c196348..ecf13316d41 100644 --- a/appserver/tests/admin/tests/src/test/java/org/glassfish/main/admin/test/rest/RestTestBase.java +++ b/appserver/tests/admin/tests/src/test/java/org/glassfish/main/admin/test/rest/RestTestBase.java @@ -95,7 +95,9 @@ public static void captureLogAndCloseClient(final TestInfo testInfo) throws Exce ensureWritableDir(reportDir); File reportFile = new File(reportDir, testInfo.getTestClass().orElseThrow().getName() + "-server.log"); - FileUtils.copy(response.readEntity(InputStream.class), reportFile, Long.MAX_VALUE); + try (InputStream readEntity = response.readEntity(InputStream.class)) { + FileUtils.copy(readEntity, reportFile); + } } } diff --git a/nucleus/common/common-util/src/main/java/com/sun/enterprise/util/io/FileUtils.java b/nucleus/common/common-util/src/main/java/com/sun/enterprise/util/io/FileUtils.java index d44703cbe29..3b89d8b9c71 100644 --- a/nucleus/common/common-util/src/main/java/com/sun/enterprise/util/io/FileUtils.java +++ b/nucleus/common/common-util/src/main/java/com/sun/enterprise/util/io/FileUtils.java @@ -40,6 +40,7 @@ import java.nio.channels.ReadableByteChannel; import java.nio.channels.WritableByteChannel; import java.nio.file.Files; +import java.nio.file.StandardCopyOption; import java.util.Collection; import java.util.Locale; import java.util.Set; @@ -609,8 +610,10 @@ private static File relativize(File parent, File child) { * retry count is reached. * * @param work the RetriableWork implementation to be run - * @return the number of retries performed; 0 indicates the work succeeded without having to retry - * @deprecated The situation usually means there's an IO leak. + * @return the number of retries performed; 0 indicates the work succeeded without having to + * retry + * @deprecated The situation usually means there's an IO leak. It can be used also on Windows OS + * when many threads are trying to access the same file. */ @Deprecated private static int doWithRetry(RetriableWork work) { @@ -740,18 +743,22 @@ static boolean isValidString(String s) { /** - * FIXME: Document and write test with large zip file to see if it wouldn't be better to use - * BufferedInputStream and BufferedOutputStream. - * FIXME: Usually used with JarFile and it's entry. Add API. + * Fast method using NIO to copy data from the input to the output file, when you already do + * know the size of the input. *

* WARNING: Don't use it when you don't know the byteCount value. * * @param in It will be closed after processing. * @param out Target output file. * @param byteCount count of bytes to be transferred. - * @throws IOException + * @throws IOException if the operation failed. + * @throws IllegalArgumentException if the byte count is less then 0 or equal to + * {@link Long#MAX_VALUE} (obvious hacks) */ - public static void copy(InputStream in, File out, long byteCount) throws IOException { + public static void copy(InputStream in, File out, long byteCount) throws IOException, IllegalArgumentException { + if (byteCount < 0 || byteCount >= Long.MAX_VALUE) { + throw new IllegalArgumentException("If you don't know the byte count, don't use this method!"); + } try ( ReadableByteChannel inputChannel = Channels.newChannel(in); FileOutputStream output = new FileOutputStream(out)) { @@ -760,6 +767,19 @@ public static void copy(InputStream in, File out, long byteCount) throws IOExcep } + /** + * This method should be used instead of {@link #copy(InputStream, File, long)} if you don't + * know the size of the input stream. + * + * @param in It will NOT be closed after processing. That is caller's responsibility. + * @param out Target output file. If the file already exists, it will be overwritten! + * @throws IOException + */ + public static void copy(InputStream in, File out) throws IOException { + Files.copy(in, out.toPath(), StandardCopyOption.REPLACE_EXISTING); + } + + /** * Copies stream with internal 8K buffer. * diff --git a/nucleus/common/common-util/src/main/java/org/glassfish/admin/payload/PayloadFilesManager.java b/nucleus/common/common-util/src/main/java/org/glassfish/admin/payload/PayloadFilesManager.java index be4a9ed2483..1ceb9b6cb07 100644 --- a/nucleus/common/common-util/src/main/java/org/glassfish/admin/payload/PayloadFilesManager.java +++ b/nucleus/common/common-util/src/main/java/org/glassfish/admin/payload/PayloadFilesManager.java @@ -436,7 +436,7 @@ private File extractFile(final Payload.Part part, final String outputName) throw if (!extractedFile.isDirectory()) { try (InputStream is = part.getInputStream()) { - FileUtils.copy(is, extractedFile, Long.MAX_VALUE); + FileUtils.copy(is, extractedFile); } } diff --git a/nucleus/common/common-util/src/main/java/org/glassfish/admin/payload/PayloadImpl.java b/nucleus/common/common-util/src/main/java/org/glassfish/admin/payload/PayloadImpl.java index 8aca45c939a..0d742df0899 100644 --- a/nucleus/common/common-util/src/main/java/org/glassfish/admin/payload/PayloadImpl.java +++ b/nucleus/common/common-util/src/main/java/org/glassfish/admin/payload/PayloadImpl.java @@ -17,15 +17,21 @@ package org.glassfish.admin.payload; -import com.sun.enterprise.util.io.FileUtils; - -import java.io.*; +import java.io.BufferedInputStream; +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; import java.net.URI; import java.net.URLConnection; import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.Properties; + import org.glassfish.api.admin.Payload; /** diff --git a/nucleus/common/common-util/src/test/java/com/sun/enterprise/util/io/FileUtilsTest.java b/nucleus/common/common-util/src/test/java/com/sun/enterprise/util/io/FileUtilsTest.java index ec4cb2b1039..a10c1930226 100644 --- a/nucleus/common/common-util/src/test/java/com/sun/enterprise/util/io/FileUtilsTest.java +++ b/nucleus/common/common-util/src/test/java/com/sun/enterprise/util/io/FileUtilsTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2022 Contributors to the Eclipse Foundation + * Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation * Copyright (c) 2011, 2018 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the @@ -22,26 +22,27 @@ import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; +import java.io.IOException; import java.io.InputStream; -import java.nio.file.Files; -import org.junit.jupiter.api.BeforeAll; + import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.DynamicTest.stream; /** * @author wnevins * @author David Matejcek */ public class FileUtilsTest { + + @TempDir private static File tempDir; - @BeforeAll - public static void init() throws Exception { - tempDir = Files.createTempDirectory(FileUtilsTest.class.getSimpleName()).toFile(); - } @Test public void testMkdirsMaybe() { @@ -81,34 +82,59 @@ public void testCopyDirectoriesFiles() throws Exception { } + @Test + public void testCopyStreamWithKnownSizeToFile() throws Exception { + File outputFile = new File(tempDir, "outputFile"); + File testFile = new File(FileUtilsTest.class.getResource("/adminport.xml").toURI()); + long length = testFile.length(); + try (FileInputStream stream = new FileInputStream(testFile)) { + FileUtils.copy(stream, outputFile, length); + assertEquals(testFile.length(), outputFile.length()); + assertThrows(IOException.class, () -> stream.available()); + } + // do that once again to verify that the file was not appended or the operation blocked. + try (FileInputStream stream = new FileInputStream(testFile)) { + FileUtils.copy(stream, outputFile, length); + assertEquals(testFile.length(), outputFile.length()); + assertThrows(IOException.class, () -> stream.available()); + } + } + + @Test public void testCopyStreamToFile() throws Exception { File outputFile = new File(tempDir, "outputFile"); File testFile = new File(FileUtilsTest.class.getResource("/adminport.xml").toURI()); - FileInputStream stream = new FileInputStream(testFile); - FileUtils.copy(stream, outputFile, Long.MAX_VALUE); - assertEquals(testFile.length(), outputFile.length()); + try (FileInputStream stream = new FileInputStream(testFile)) { + FileUtils.copy(stream, outputFile); + assertEquals(testFile.length(), outputFile.length()); + assertEquals(0, stream.available(), "available bytes"); + } } @Test public void testCopyFileStreamToFileStream() throws Exception { File outputFile = new File(tempDir, "outputFile"); - FileOutputStream output = new FileOutputStream(outputFile); File testFile = new File(FileUtilsTest.class.getResource("/adminport.xml").toURI()); - FileInputStream inputStream = new FileInputStream(testFile); - FileUtils.copy(inputStream, output); - assertEquals(testFile.length(), outputFile.length()); + try (FileOutputStream output = new FileOutputStream(outputFile); + FileInputStream inputStream = new FileInputStream(testFile)) { + FileUtils.copy(inputStream, output); + assertEquals(testFile.length(), outputFile.length()); + assertEquals(0, inputStream.available(), "available bytes"); + } } @Test public void testCopyCLStreamToStream() throws Exception { File outputFile = new File(tempDir, "outputFile"); - BufferedOutputStream output = new BufferedOutputStream(new FileOutputStream(outputFile)); File testFile = new File(FileUtilsTest.class.getResource("/adminport.xml").toURI()); - InputStream inputStream = new BufferedInputStream(FileUtilsTest.class.getResourceAsStream("/adminport.xml")); - FileUtils.copy(inputStream, output); - assertEquals(testFile.length(), outputFile.length()); + try (BufferedOutputStream output = new BufferedOutputStream(new FileOutputStream(outputFile)); + InputStream inputStream = new BufferedInputStream(FileUtilsTest.class.getResourceAsStream("/adminport.xml"))) { + FileUtils.copy(inputStream, output); + assertEquals(testFile.length(), outputFile.length()); + assertEquals(0, inputStream.available(), "available bytes"); + } } } diff --git a/nucleus/core/kernel/src/main/java/com/sun/enterprise/v3/admin/CheckpointHelper.java b/nucleus/core/kernel/src/main/java/com/sun/enterprise/v3/admin/CheckpointHelper.java index cd8a5b5a5d5..d9185bf4bdc 100644 --- a/nucleus/core/kernel/src/main/java/com/sun/enterprise/v3/admin/CheckpointHelper.java +++ b/nucleus/core/kernel/src/main/java/com/sun/enterprise/v3/admin/CheckpointHelper.java @@ -372,7 +372,7 @@ private void loadOutbound(Outbound outbound, File outboundFile) throws IOExcepti Part part = parts.next(); File sourceFile = File.createTempFile("source", "", topDir); try (InputStream inputStream = part.getInputStream()) { - FileUtils.copy(inputStream, sourceFile, Long.MAX_VALUE); + FileUtils.copy(inputStream, sourceFile); } outbound.addPart(part.getContentType(), part.getName(), part.getProperties(), new FileInputStream(sourceFile)); } From 50d9e62167a0a705f8cc207d651b2a73887cf443 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Mat=C4=9Bj=C4=8Dek?= Date: Sat, 7 Oct 2023 01:36:00 +0200 Subject: [PATCH 08/12] Renewed resource leak - the implementation depends on it. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - it has to be refactored or rewritten to a more robust state Signed-off-by: David Matějček --- .../reader/MultipartProprietaryReader.java | 98 ++++++++++--------- 1 file changed, 51 insertions(+), 47 deletions(-) diff --git a/nucleus/admin/util/src/main/java/com/sun/enterprise/admin/remote/reader/MultipartProprietaryReader.java b/nucleus/admin/util/src/main/java/com/sun/enterprise/admin/remote/reader/MultipartProprietaryReader.java index 508064b901f..ebbce7fccf0 100644 --- a/nucleus/admin/util/src/main/java/com/sun/enterprise/admin/remote/reader/MultipartProprietaryReader.java +++ b/nucleus/admin/util/src/main/java/com/sun/enterprise/admin/remote/reader/MultipartProprietaryReader.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Contributors to the Eclipse Foundation + * Copyright (c) 2022, 2023 Contributors to the Eclipse Foundation * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the @@ -34,6 +34,9 @@ import org.jvnet.mimepull.MIMEMessage; import org.jvnet.mimepull.MIMEPart; +import static java.nio.charset.StandardCharsets.ISO_8859_1; +import static java.nio.charset.StandardCharsets.UTF_8; + /** * * @author martinmares @@ -64,62 +67,63 @@ public ParamsWithPayload readFrom(final HttpURLConnection urlConnection) throws @Override public ParamsWithPayload readFrom(final InputStream is, final String contentType) throws IOException { - RestPayloadImpl.Inbound payload = null; - ActionReport actionReport = null; - ParameterMap parameters = null; Properties mtProps = parseHeaderParams(contentType); final String boundary = mtProps.getProperty("boundary"); if (!StringUtils.ok(boundary)) { throw new IOException("ContentType does not define boundary"); } - try (MIMEMessage mimeMessage = new MIMEMessage(is, boundary, new MIMEConfig())) { - // Parse - for (MIMEPart mimePart : mimeMessage.getAttachments()) { - String cd = getFirst(mimePart.getHeader("Content-Disposition")); - if (!StringUtils.ok(cd)) { - cd = "file"; + + // FIXME: Big refactoring required because of possible resource leaks: + // MIMEMessage produces MIMEPart objects based on the is parameter. + // All these objects are Closeable. + // The final result of this method is the payload, based on mimePart object. + // That is used later, and at least in one branch none of these objecs can be closed, + // because the payload's input stream would be closed too. + final MIMEMessage mimeMessage = new MIMEMessage(is, boundary, new MIMEConfig()); + RestPayloadImpl.Inbound payload = null; + ActionReport actionReport = null; + ParameterMap parameters = null; + // Parse + for (MIMEPart mimePart : mimeMessage.getAttachments()) { + String cd = getFirst(mimePart.getHeader("Content-Disposition")); + cd = StringUtils.ok(cd) ? cd.trim() : "file"; + Properties cdParams = parseHeaderParams(cd); + // 3 types of content disposition + if (cd.startsWith("form-data")) { + // COMMAND PARAMETER + if (!StringUtils.ok(cdParams.getProperty("name"))) { + throw new IOException("Form-data Content-Disposition does not contains name parameter."); } - cd = cd.trim(); - Properties cdParams = parseHeaderParams(cd); - // 3 types of content disposition - if (cd.startsWith("form-data")) { - // COMMAND PARAMETER - if (!StringUtils.ok(cdParams.getProperty("name"))) { - throw new IOException("Form-data Content-Disposition does not contains name parameter."); - } - if (parameters == null) { - parameters = new ParameterMap(); - } - parameters.add(cdParams.getProperty("name"), stream2String(mimePart.readOnce())); - } else if (mimePart.getContentType() != null - && mimePart.getContentType().startsWith("application/json")) { - // ACTION REPORT - actionReport = actionReportReader.readFrom(mimePart.readOnce(), "application/json"); + if (parameters == null) { + parameters = new ParameterMap(); + } + parameters.add(cdParams.getProperty("name"), stream2String(mimePart.readOnce())); + } else if (mimePart.getContentType() != null && mimePart.getContentType().startsWith("application/json")) { + // ACTION REPORT + actionReport = actionReportReader.readFrom(mimePart.readOnce(), "application/json"); + } else { + // PAYLOAD + final String name; + if (cdParams.containsKey("name")) { + name = new String(cdParams.getProperty("name").getBytes(ISO_8859_1), UTF_8); + } else if (cdParams.containsKey("filename")) { + name = cdParams.getProperty("filename"); } else { - // PAYLOAD - String name = "noname"; - if (cdParams.containsKey("name")) { - name = cdParams.getProperty("name"); - name = new String(name.getBytes("ISO8859-1"), "UTF-8"); - } else if (cdParams.containsKey("filename")) { - name = cdParams.getProperty("filename"); - } - if (payload == null) { - payload = new RestPayloadImpl.Inbound(); - } - String ct = mimePart.getContentType(); - if (!StringUtils.ok(ct) || ct.trim().startsWith("text/plain")) { - payload.add(name, stream2String(mimePart.readOnce()), mimePart.getAllHeaders()); - } else { - payload.add(name, mimePart.read(), ct, mimePart.getAllHeaders()); - } + name = "noname"; + } + if (payload == null) { + payload = new RestPayloadImpl.Inbound(); + } + final String ct = mimePart.getContentType(); + if (StringUtils.ok(ct) && !ct.trim().startsWith("text/plain")) { + payload.add(name, mimePart.read(), ct, mimePart.getAllHeaders()); + } else { + payload.add(name, stream2String(mimePart.readOnce()), mimePart.getAllHeaders()); } } - // Result - return new ParamsWithPayload(payload, parameters, actionReport); - } finally { - is.close(); } + // Result + return new ParamsWithPayload(payload, parameters, actionReport); } /** From 866309988700e1e3f3fedbbe45e1b08e2a8a7867 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Mat=C4=9Bj=C4=8Dek?= Date: Tue, 20 Feb 2024 18:16:47 +0100 Subject: [PATCH 09/12] Fixes based on self-review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: David Matějček # Conflicts: # appserver/jms/jms-core/src/main/java/com/sun/enterprise/connectors/jms/system/JmsProviderLifecycle.java --- .../client/acc/ACCStartupContext.java | 2 +- .../client/acc/MainClassLaunchable.java | 2 +- .../server/core/AppClientDeployer.java | 90 ++++++------- .../server/core/AppClientDeployerHelper.java | 19 ++- .../core/AppClientGroupFacadeGenerator.java | 2 +- .../StandaloneAppClientDeployerHelper.java | 27 +--- .../archivist/ApplicationArchivist.java | 2 +- .../deployment/archivist/Archivist.java | 9 +- .../archivist/DescriptorArchivist.java | 13 +- .../archivist/ExtensionsArchivist.java | 2 +- .../javaee/core/deployment/DolProvider.java | 122 +++++++++++------- .../javaee/full/deployment/EarDeployer.java | 2 +- .../javaee/full/deployment/EarHandler.java | 6 +- .../timer/PersistentEJBTimerService.java | 5 +- .../webservices/metroglue/MetroContainer.java | 8 +- .../admin/cli/embeddable/DeployerImpl.java | 50 +++---- .../enterprise/admin/launcher/GFLauncher.java | 11 +- .../admin/rest/resources/StatusGenerator.java | 4 +- .../admin/remote/RemoteResponseManager.java | 2 +- .../ActionReportJsonProprietaryReader.java | 2 +- ...dminCommandStateJsonProprietaryReader.java | 2 +- ...aramsWithPayloadJsonProprietaryReader.java | 2 +- ...rogressStatusDTOJsonProprietaryReader.java | 2 +- ...gressStatusEventJsonProprietaryReader.java | 2 +- .../reader/StringProprietaryReader.java | 9 +- .../admin/cluster/CreateNodeSshCommand.java | 2 +- .../cluster/SecureAdminBootstrapHelper.java | 6 +- .../v3/admin/cluster/SetupSshCommand.java | 2 +- .../cli/cluster/InstallNodeSshCommand.java | 2 +- .../cli/cluster/NativeRemoteCommandsBase.java | 2 +- .../cluster/SynchronizeInstanceCommand.java | 2 +- .../cli/cluster/UninstallNodeSshCommand.java | 2 +- .../glassfish/cluster/ssh/util/SSHUtil.java | 2 +- .../glassfish/admin/amx/util/AMXDebug.java | 4 +- .../enterprise/universal/io/SmartFile.java | 2 +- .../com/sun/enterprise/util/io/FileUtils.java | 52 +++++--- .../com/sun/enterprise/util/zip/ZipFile.java | 5 +- .../sun/enterprise/util/io/FileUtilsTest.java | 11 ++ .../archive/ReadableArchiveAdapter.java | 8 +- .../internal/deployment/GenericHandler.java | 2 +- .../org/glassfish/embeddable/Deployer.java | 2 +- .../v3/server/ApplicationLifecycle.java | 53 +++----- .../deployment/admin/DeployCommand.java | 6 +- .../enterprise/deploy/shared/FileArchive.java | 20 +-- .../common/DeploymentContextImpl.java | 7 +- .../deployment/common/DeploymentUtils.java | 2 +- .../deployment/common/ModuleExploder.java | 1 + .../versioning/VersioningService.java | 19 +-- .../common/EmbeddedSecurityLifeCycle.java | 15 +-- .../embedded/EmbeddedSecurityUtil.java | 6 +- 50 files changed, 308 insertions(+), 324 deletions(-) diff --git a/appserver/appclient/client/acc/src/main/java/org/glassfish/appclient/client/acc/ACCStartupContext.java b/appserver/appclient/client/acc/src/main/java/org/glassfish/appclient/client/acc/ACCStartupContext.java index 335a98c800f..84f4e58a9b9 100644 --- a/appserver/appclient/client/acc/src/main/java/org/glassfish/appclient/client/acc/ACCStartupContext.java +++ b/appserver/appclient/client/acc/src/main/java/org/glassfish/appclient/client/acc/ACCStartupContext.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Contributors to the Eclipse Foundation + * Copyright (c) 2022, 2023 Contributors to the Eclipse Foundation * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the diff --git a/appserver/appclient/client/acc/src/main/java/org/glassfish/appclient/client/acc/MainClassLaunchable.java b/appserver/appclient/client/acc/src/main/java/org/glassfish/appclient/client/acc/MainClassLaunchable.java index 36ba88c7494..9ae37b1ceed 100644 --- a/appserver/appclient/client/acc/src/main/java/org/glassfish/appclient/client/acc/MainClassLaunchable.java +++ b/appserver/appclient/client/acc/src/main/java/org/glassfish/appclient/client/acc/MainClassLaunchable.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Contributors to the Eclipse Foundation + * Copyright (c) 2022, 2023 Contributors to the Eclipse Foundation * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the diff --git a/appserver/appclient/server/core/src/main/java/org/glassfish/appclient/server/core/AppClientDeployer.java b/appserver/appclient/server/core/src/main/java/org/glassfish/appclient/server/core/AppClientDeployer.java index ae79e4a2703..432f6e1195e 100644 --- a/appserver/appclient/server/core/src/main/java/org/glassfish/appclient/server/core/AppClientDeployer.java +++ b/appserver/appclient/server/core/src/main/java/org/glassfish/appclient/server/core/AppClientDeployer.java @@ -1,4 +1,5 @@ /* + * Copyright (c) 2023 Contributors to the Eclipse Foundation * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the @@ -16,40 +17,41 @@ package org.glassfish.appclient.server.core; -import com.sun.enterprise.config.serverbeans.Config; import com.sun.enterprise.config.serverbeans.Applications; -import com.sun.enterprise.module.HK2Module; -import java.io.IOException; +import com.sun.enterprise.config.serverbeans.Config; import com.sun.enterprise.config.serverbeans.Domain; import com.sun.enterprise.deployment.Application; import com.sun.enterprise.deployment.ApplicationClientDescriptor; import com.sun.enterprise.deployment.archivist.AppClientArchivist; +import com.sun.enterprise.module.HK2Module; import com.sun.enterprise.module.ModulesRegistry; -import com.sun.logging.LogDomains; + +import jakarta.inject.Inject; +import jakarta.inject.Named; +import jakarta.inject.Singleton; + +import java.io.IOException; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import java.util.jar.Attributes; import java.util.logging.Logger; -import jakarta.inject.Inject; -import jakarta.inject.Named; +import org.glassfish.api.admin.ServerEnvironment; import org.glassfish.api.deployment.DeploymentContext; import org.glassfish.api.deployment.MetaData; import org.glassfish.api.deployment.UndeployCommandParameters; -import org.glassfish.appclient.server.core.jws.servedcontent.ASJarSigner; -import org.glassfish.deployment.common.DeploymentException; -import org.glassfish.javaee.core.deployment.JavaEEDeployer; - -import org.jvnet.hk2.annotations.Service; -import org.glassfish.hk2.api.PostConstruct; -import jakarta.inject.Singleton; -import org.glassfish.api.admin.ServerEnvironment; import org.glassfish.appclient.server.core.jws.JWSAdapterManager; import org.glassfish.appclient.server.core.jws.JavaWebStartInfo; +import org.glassfish.appclient.server.core.jws.servedcontent.ASJarSigner; import org.glassfish.deployment.common.Artifacts; +import org.glassfish.deployment.common.DeploymentException; import org.glassfish.deployment.common.DeploymentUtils; +import org.glassfish.hk2.api.PostConstruct; +import org.glassfish.javaee.core.deployment.JavaEEDeployer; +import org.jvnet.hk2.annotations.Service; + /** * AppClient module deployer. *

@@ -160,14 +162,14 @@ public class AppClientDeployer * Maps the app name to the user-friendly context root for that app. */ private final Map appAndClientNameToUserFriendlyContextRoot = - new HashMap(); + new HashMap<>(); /** the class loader which knows about the org.glassfish.main.appclient.gf-client-module */ private ClassLoader gfClientModuleClassLoader; - /* + /** * Each app client server application will listen for config change * events - for creation, deletion, or change of java-web-start-enabled * property settings. Because they are not handled as services hk2 will @@ -177,8 +179,7 @@ public class AppClientDeployer * all app client server applications so the deployer can forward * notifications to each app client server app. */ - final private Set appClientApps = - new HashSet(); + private final Set appClientApps = new HashSet<>(); public AppClientDeployer() { } @@ -282,8 +283,7 @@ protected void generateArtifacts(DeploymentContext dc) throws DeploymentExceptio * @param helper * @param dc */ - private void recordUserFriendlyContextRoot(final AppClientDeployerHelper helper, - final DeploymentContext dc) { + private void recordUserFriendlyContextRoot(final AppClientDeployerHelper helper, final DeploymentContext dc) { final String path = JWSAdapterManager.userFriendlyContextRoot(helper.appClientDesc(), dc.getAppProps()); dc.getModuleProps().put("jws.user.friendly.path", path); } @@ -322,23 +322,17 @@ private AppClientDeployerHelper getSavedHelperOrCreateHelper(final DeploymentCon final String key = HELPER_KEY_NAME + moduleURI(dc); AppClientDeployerHelper h = null; - final AppClientDeployerHelper.Proxy p = dc.getTransientAppMetaData(key, - AppClientDeployerHelper.Proxy.class); + final AppClientDeployerHelper.Proxy p = dc.getTransientAppMetaData(key, AppClientDeployerHelper.Proxy.class); if (p != null) { h = p.helper(); } - if (h == null) { - h = dc.getTransientAppMetaData(key, - StandaloneAppClientDeployerHelper.class); + h = dc.getTransientAppMetaData(key, StandaloneAppClientDeployerHelper.class); } if (h == null) { - /* - * We are probably loading a previously-deployed app client, so - * the helper has not be created yet. Create it. - */ - h = createAndSaveHelper(dc, - gfClientModuleClassLoader); + // We are probably loading a previously-deployed app client, so + // the helper has not be created yet. Create it. + h = createAndSaveHelper(dc, gfClientModuleClassLoader); } return h; } @@ -348,20 +342,20 @@ private String moduleURI(final DeploymentContext dc) { return acd.getModuleDescriptor().getArchiveUri(); } - public void recordContextRoot(final String appName, - final String clientURIWithinEAR, - final String userFriendlyContextRoot) { - appAndClientNameToUserFriendlyContextRoot.put( - keyToAppAndClientNameMap(appName, clientURIWithinEAR), - userFriendlyContextRoot); + + public void recordContextRoot(final String appName, final String clientURIWithinEAR, + final String userFriendlyContextRoot) { + String key = keyToAppAndClientNameMap(appName, clientURIWithinEAR); + appAndClientNameToUserFriendlyContextRoot.put(key, userFriendlyContextRoot); } - public void removeContextRoot(final String appName, - final String clientURIWithinEAR) { - appAndClientNameToUserFriendlyContextRoot.remove( - keyToAppAndClientNameMap(appName, clientURIWithinEAR)); + + public void removeContextRoot(final String appName, final String clientURIWithinEAR) { + String key = keyToAppAndClientNameMap(appName, clientURIWithinEAR); + appAndClientNameToUserFriendlyContextRoot.remove(key); } + /** * Returns the user-friendly context root for the specified app client. *

@@ -371,19 +365,13 @@ public void removeContextRoot(final String appName, * @param clientModuleURI * @return */ - public String userFriendlyContextRoot(final String appName, - final String clientModuleURI) { - return appAndClientNameToUserFriendlyContextRoot.get( - keyToAppAndClientNameMap(appName, clientModuleURI)); + public String userFriendlyContextRoot(final String appName, final String clientModuleURI) { + String key = keyToAppAndClientNameMap(appName, clientModuleURI); + return appAndClientNameToUserFriendlyContextRoot.get(key); } - - private String keyToAppAndClientNameMap(final String appName, - final String moduleURIText) { + private String keyToAppAndClientNameMap(final String appName, final String moduleURIText) { return appName + "/" + (moduleURIText == null ? appName : moduleURIText); } - - - } diff --git a/appserver/appclient/server/core/src/main/java/org/glassfish/appclient/server/core/AppClientDeployerHelper.java b/appserver/appclient/server/core/src/main/java/org/glassfish/appclient/server/core/AppClientDeployerHelper.java index ba980a5780e..4a016dc76fd 100644 --- a/appserver/appclient/server/core/src/main/java/org/glassfish/appclient/server/core/AppClientDeployerHelper.java +++ b/appserver/appclient/server/core/src/main/java/org/glassfish/appclient/server/core/AppClientDeployerHelper.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Contributors to the Eclipse Foundation + * Copyright (c) 2022, 2023 Contributors to the Eclipse Foundation * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the @@ -290,7 +290,7 @@ public abstract void createAndAddLibraryJNLPs(final AppClientDeployerHelper help throws IOException; public Map> signingAliasToJar() { - return Collections.EMPTY_MAP; + return Collections.emptyMap(); } public final DeploymentContext dc() { @@ -480,7 +480,17 @@ protected void addClientPolicyFiles(final OutputJarArchive clientFacadeArchive) } } - protected abstract void copyFileToTopLevelJAR(final OutputJarArchive clientFacadeArchive, final File f, final String path) throws IOException; + /** + * Copies a file's contents to the top-level JAR generated by this deployment. + * + * @param clientFacadeArchive + * @param inputFile + * @param pathInJar + * @throws IOException + */ + protected abstract void copyFileToTopLevelJAR(final OutputJarArchive clientFacadeArchive, final File inputFile, + final String pathInJar) throws IOException; + protected final void generateAppClientFacade() throws IOException, URISyntaxException { try (OutputJarArchive facadeArchive = new OutputJarArchive()) { @@ -568,7 +578,7 @@ static void copy(ReadableArchive source, WritableArchive target, String entryNam FileUtils.copy(is, os); } catch (ZipException ze) { // this is a duplicate... - return; + logger.log(Level.WARNING, "Putting of the entry failed for " + entryName, ze); } } } @@ -585,6 +595,7 @@ static void copyArchive(ReadableArchive source, WritableArchive target, Set dynamicContent) { } - /** - * Copies a file's contents to the top-level JAR generated by this - * deployment. - * - * @param clientFacadeArchive - * @param f - * @param path - * @throws IOException - */ - @Override - protected void copyFileToTopLevelJAR(final OutputJarArchive clientFacadeArchive, final File f, final String path) throws IOException { - copyToArchive(f, clientFacadeArchive, path); - } - private void copyToArchive(final File inputFile, final OutputJarArchive outputArchive, final String pathInJar) throws IOException { - try (WritableArchiveEntry os = outputArchive.putNextEntry(pathInJar); - InputStream is = new FileInputStream(inputFile)) { - FileUtils.copy(is, os); + @Override + protected void copyFileToTopLevelJAR(final OutputJarArchive clientFacadeArchive, final File inputFile, + final String pathInJar) throws IOException { + try (WritableArchiveEntry os = clientFacadeArchive.putNextEntry(pathInJar)) { + FileUtils.copy(inputFile, os); } } - @Override public FixedContent fixedContentWithinEAR(String uriString) { /* diff --git a/appserver/deployment/dol/src/main/java/com/sun/enterprise/deployment/archivist/ApplicationArchivist.java b/appserver/deployment/dol/src/main/java/com/sun/enterprise/deployment/archivist/ApplicationArchivist.java index 148c9a3f9f6..b402b38a84e 100644 --- a/appserver/deployment/dol/src/main/java/com/sun/enterprise/deployment/archivist/ApplicationArchivist.java +++ b/appserver/deployment/dol/src/main/java/com/sun/enterprise/deployment/archivist/ApplicationArchivist.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Contributors to the Eclipse Foundation + * Copyright (c) 2022, 2023 Contributors to the Eclipse Foundation * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the diff --git a/appserver/deployment/dol/src/main/java/com/sun/enterprise/deployment/archivist/Archivist.java b/appserver/deployment/dol/src/main/java/com/sun/enterprise/deployment/archivist/Archivist.java index a616c517fce..427962ec6b4 100644 --- a/appserver/deployment/dol/src/main/java/com/sun/enterprise/deployment/archivist/Archivist.java +++ b/appserver/deployment/dol/src/main/java/com/sun/enterprise/deployment/archivist/Archivist.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Contributors to the Eclipse Foundation + * Copyright (c) 2022, 2023 Contributors to the Eclipse Foundation * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the @@ -1297,12 +1297,12 @@ protected static File getTempFile(File fileOrDir) throws IOException { * @param archive abstraction to use when adding the file * @param filePath to the file to add * @param entryName the entry name in the archive + * @throws IOException */ protected static void addFileToArchive(WritableArchive archive, String filePath, String entryName) throws IOException { - try (FileInputStream is = new FileInputStream(new File(filePath)); - WritableArchiveEntry os = archive.putNextEntry(entryName)) { - FileUtils.copy(is, os); + try (WritableArchiveEntry os = archive.putNextEntry(entryName)) { + FileUtils.copy(new File(filePath), os); } } @@ -1313,6 +1313,7 @@ protected static void addFileToArchive(WritableArchive archive, String filePath, * @param in jar file * @param out jar file * @param ignored entry names to not copy from to source jar file + * @throws IOException */ protected void copyJarElements(ReadableArchive in, WritableArchive out, Set ignored) throws IOException { Enumeration entries = in.entries(); diff --git a/appserver/deployment/dol/src/main/java/com/sun/enterprise/deployment/archivist/DescriptorArchivist.java b/appserver/deployment/dol/src/main/java/com/sun/enterprise/deployment/archivist/DescriptorArchivist.java index cf2753c5e38..f76014d7b53 100644 --- a/appserver/deployment/dol/src/main/java/com/sun/enterprise/deployment/archivist/DescriptorArchivist.java +++ b/appserver/deployment/dol/src/main/java/com/sun/enterprise/deployment/archivist/DescriptorArchivist.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Contributors to the Eclipse Foundation + * Copyright (c) 2022, 2023 Contributors to the Eclipse Foundation * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the @@ -39,7 +39,7 @@ @Service public class DescriptorArchivist { @Inject - protected ArchivistFactory archivistFactory; + private ArchivistFactory archivistFactory; @Inject private Provider archivistProvider; @@ -53,13 +53,13 @@ public class DescriptorArchivist { public void write(Application application, ReadableArchive in, WritableArchive out) throws IOException { if (application.isVirtual()) { ModuleDescriptor aModule = application.getModules().iterator().next(); - Archivist moduleArchivist = archivistFactory.getArchivist(aModule.getModuleType()); + Archivist moduleArchivist = archivistFactory.getArchivist(aModule.getModuleType()); write(aModule.getDescriptor(), moduleArchivist, in, out); } else { // this is a real application. // let's start by writing out all submodules deployment descriptors for (ModuleDescriptor aModule : application.getModules()) { - Archivist moduleArchivist = archivistFactory.getArchivist(aModule.getModuleType()); + Archivist moduleArchivist = archivistFactory.getArchivist(aModule.getModuleType()); try (WritableArchive moduleArchive = out.createSubArchive(aModule.getArchiveUri()); ReadableArchive moduleArchive2 = in.getSubArchive(aModule.getArchiveUri())) { write(aModule.getDescriptor(), moduleArchivist, moduleArchive2, moduleArchive); @@ -80,9 +80,10 @@ public void write(Application application, ReadableArchive in, WritableArchive o * @param archivist responsible for writing such bundle type * @param in archive to read from * @param out archive to write to + * @throws IOException */ - protected void write(BundleDescriptor bundle, Archivist archivist, ReadableArchive in, WritableArchive out) - throws IOException { + protected void write(BundleDescriptor bundle, Archivist archivist, ReadableArchive in, + WritableArchive out) throws IOException { archivist.setDescriptor(bundle); archivist.writeDeploymentDescriptors(in, out); } diff --git a/appserver/deployment/dol/src/main/java/com/sun/enterprise/deployment/archivist/ExtensionsArchivist.java b/appserver/deployment/dol/src/main/java/com/sun/enterprise/deployment/archivist/ExtensionsArchivist.java index 2e2f5f41586..2fa08979009 100644 --- a/appserver/deployment/dol/src/main/java/com/sun/enterprise/deployment/archivist/ExtensionsArchivist.java +++ b/appserver/deployment/dol/src/main/java/com/sun/enterprise/deployment/archivist/ExtensionsArchivist.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Contributors to the Eclipse Foundation + * Copyright (c) 2022, 2023 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 diff --git a/appserver/deployment/jakartaee-core/src/main/java/org/glassfish/javaee/core/deployment/DolProvider.java b/appserver/deployment/jakartaee-core/src/main/java/org/glassfish/javaee/core/deployment/DolProvider.java index 515ee0fac21..8653a92b125 100644 --- a/appserver/deployment/jakartaee-core/src/main/java/org/glassfish/javaee/core/deployment/DolProvider.java +++ b/appserver/deployment/jakartaee-core/src/main/java/org/glassfish/javaee/core/deployment/DolProvider.java @@ -21,7 +21,6 @@ import com.sun.enterprise.config.serverbeans.Domain; import com.sun.enterprise.config.serverbeans.Module; import com.sun.enterprise.deploy.shared.ArchiveFactory; -import com.sun.enterprise.deploy.shared.FileArchive; import com.sun.enterprise.deployment.Application; import com.sun.enterprise.deployment.BundleDescriptor; import com.sun.enterprise.deployment.archivist.ApplicationArchivist; @@ -42,6 +41,8 @@ import java.io.File; import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URISyntaxException; import java.util.Collection; import java.util.List; import java.util.logging.Level; @@ -270,67 +271,88 @@ public String getNameFor(ReadableArchive archive, DeploymentContext context) { * @param archive the archive for the application */ public Application processDeploymentMetaData(ReadableArchive archive) throws Exception { - File tmpFile = null; - ExtendedDeploymentContext context = null; - Logger logger = Logger.getAnonymousLogger(); - ClassLoader cl = null; - try { - String archiveName = Util.getURIName(archive.getURI()); - ArchiveHandler archiveHandler = deployment.getArchiveHandler(archive); - if (archiveHandler==null) { - throw new IllegalArgumentException(localStrings.getLocalString("deploy.unknownarchivetype", - "Archive type of {0} was not recognized", archiveName)); - } + final ArchiveHandler archiveHandler = deployment.getArchiveHandler(archive); + if (archiveHandler == null) { + throw new IllegalArgumentException(localStrings.getLocalString("deploy.unknownarchivetype", + "Archive type of {0} was not recognized", archive.getURI())); + } - DeployCommandParameters parameters = new DeployCommandParameters(new File(archive.getURI())); - ActionReport report = new HTMLActionReporter(); - context = new DeploymentContextImpl(report, archive, parameters, env); + final DeployCommandParameters parameters = new DeployCommandParameters(new File(archive.getURI())); + final ActionReport report = new HTMLActionReporter(); + final ExtendedDeploymentContext context = new DeploymentContextImpl(report, archive, parameters, env); + try { context.setArchiveHandler(archiveHandler); - String appName = archiveHandler.getDefaultApplicationName(archive, context); - parameters.name = appName; - - if (archive instanceof InputJarArchive) { - // we need to expand the archive first in this case - tmpFile = File.createTempFile(archiveName, ""); - String path = tmpFile.getAbsolutePath(); - if (!tmpFile.delete()) { - logger.log(Level.WARNING, "cannot.delete.temp.file", new Object[] {path}); - } - File tmpDir = new File(path); - tmpDir.deleteOnExit(); + parameters.name = archiveHandler.getDefaultApplicationName(archive, context); + return processDeployment(archive, archiveHandler, context); + } finally { + context.postDeployClean(true); + } + } - if (!tmpDir.exists() && !tmpDir.mkdirs()) { - throw new IOException("Unable to create directory " + tmpDir.getAbsolutePath()); - } - try (FileArchive expandedArchive = (FileArchive)archiveFactory.createArchive(tmpDir)) { - archiveHandler.expand(archive, expandedArchive, context); - context.setSource(expandedArchive); + + private Application processDeployment(ReadableArchive archive, final ArchiveHandler archiveHandler, + final ExtendedDeploymentContext context) throws IOException, URISyntaxException, MalformedURLException { + final File tmpDirectory = prepareTmpDir(archive); + try { + if (tmpDirectory != null) { + final WritableArchive expandedArchive = archiveFactory.createArchive(tmpDirectory); + archiveHandler.expand(archive, expandedArchive, context); + context.setSource((ReadableArchive) expandedArchive); + } + context.setPhase(DeploymentContextImpl.Phase.PREPARE); + context.createDeploymentClassLoader(clhProvider.get(), archiveHandler); + return processDeployment(archiveHandler, context); + } finally { + if (context.getSource() != null) { + context.getSource().close(); + } + if (tmpDirectory != null) { + try { + FileUtils.whack(tmpDirectory); + } catch (Exception e) { + Logger.getAnonymousLogger().log(Level.WARNING, + "Could not delete the temporary directory " + tmpDirectory, e); } } + } + } - context.setPhase(DeploymentContextImpl.Phase.PREPARE); - ClassLoaderHierarchy clh = clhProvider.get(); - context.createDeploymentClassLoader(clh, archiveHandler); - cl = context.getClassLoader(); + + private File prepareTmpDir(final ReadableArchive archive) throws IOException { + if (!(archive instanceof InputJarArchive)) { + return null; + } + // we need to expand the archive first in this case + final String archiveName = Util.getURIName(archive.getURI()); + final File tmpFile = File.createTempFile(archiveName, ""); + final String path = tmpFile.getAbsolutePath(); + if (!tmpFile.delete()) { + Logger.getAnonymousLogger().log(Level.WARNING, "cannot.delete.temp.file", path); + } + final File tmpDir = new File(path); + tmpDir.deleteOnExit(); + + if (!tmpDir.exists() && !tmpDir.mkdirs()) { + throw new IOException("Unable to create directory " + tmpDir.getAbsolutePath()); + } + return tmpDir; + } + + + private Application processDeployment(final ArchiveHandler archiveHandler, final ExtendedDeploymentContext context) + throws IOException { + final ClassLoader cl = context.getClassLoader(); + try { deployment.getDeployableTypes(context); deployment.getSniffers(archiveHandler, null, context); return processDOL(context); - } finally { - if (cl != null && cl instanceof PreDestroy) { + } finally { + if (cl instanceof PreDestroy) { try { PreDestroy.class.cast(cl).preDestroy(); } catch (Exception e) { - // ignore - } - } - if (context != null) { - context.postDeployClean(true); - } - if (tmpFile != null && tmpFile.exists()) { - try { - FileUtils.whack(tmpFile); - } catch (Exception e) { - // ignore + Logger.getAnonymousLogger().log(Level.WARNING, + "ClassLoader preDestroy failed for " + cl, e); } } } diff --git a/appserver/deployment/jakartaee-full/src/main/java/org/glassfish/javaee/full/deployment/EarDeployer.java b/appserver/deployment/jakartaee-full/src/main/java/org/glassfish/javaee/full/deployment/EarDeployer.java index 18ef1cde056..f3cf8b8111a 100644 --- a/appserver/deployment/jakartaee-full/src/main/java/org/glassfish/javaee/full/deployment/EarDeployer.java +++ b/appserver/deployment/jakartaee-full/src/main/java/org/glassfish/javaee/full/deployment/EarDeployer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2022 Contributors to the Eclipse Foundation. + * Copyright (c) 2022, 2023 Contributors to the Eclipse Foundation. * Copyright (c) 1997, 2022 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the diff --git a/appserver/deployment/jakartaee-full/src/main/java/org/glassfish/javaee/full/deployment/EarHandler.java b/appserver/deployment/jakartaee-full/src/main/java/org/glassfish/javaee/full/deployment/EarHandler.java index 7ad060c5ebd..cfb1150b8ed 100644 --- a/appserver/deployment/jakartaee-full/src/main/java/org/glassfish/javaee/full/deployment/EarHandler.java +++ b/appserver/deployment/jakartaee-full/src/main/java/org/glassfish/javaee/full/deployment/EarHandler.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2022 Contributors to the Eclipse Foundation. + * Copyright (c) 2022, 2023 Contributors to the Eclipse Foundation. * Copyright (c) 1997, 2022 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the @@ -18,7 +18,6 @@ package org.glassfish.javaee.full.deployment; import com.sun.enterprise.config.serverbeans.DasConfig; -import com.sun.enterprise.connectors.connector.module.RarType; import com.sun.enterprise.deploy.shared.AbstractArchiveHandler; import com.sun.enterprise.deploy.shared.ArchiveFactory; import com.sun.enterprise.deploy.shared.FileArchive; @@ -76,18 +75,15 @@ import org.glassfish.api.deployment.archive.ReadableArchive; import org.glassfish.api.deployment.archive.WarArchiveType; import org.glassfish.api.deployment.archive.WritableArchive; -import org.glassfish.appclient.server.connector.CarType; import org.glassfish.deployment.common.DeploymentContextImpl; import org.glassfish.deployment.common.DeploymentProperties; import org.glassfish.deployment.common.ModuleDescriptor; -import org.glassfish.ejb.deployment.archive.EjbType; import org.glassfish.hk2.api.PreDestroy; import org.glassfish.internal.api.DelegatingClassLoader; import org.glassfish.internal.deployment.Deployment; import org.glassfish.internal.deployment.ExtendedDeploymentContext; import org.glassfish.javaee.core.deployment.ApplicationHolder; import org.glassfish.loader.util.ASClassLoaderUtil; -import org.glassfish.web.WarType; import org.jvnet.hk2.annotations.Service; import org.xml.sax.SAXException; diff --git a/appserver/ejb/ejb-full-container/src/main/java/org/glassfish/ejb/persistent/timer/PersistentEJBTimerService.java b/appserver/ejb/ejb-full-container/src/main/java/org/glassfish/ejb/persistent/timer/PersistentEJBTimerService.java index d05b6704dec..2e74d96967d 100755 --- a/appserver/ejb/ejb-full-container/src/main/java/org/glassfish/ejb/persistent/timer/PersistentEJBTimerService.java +++ b/appserver/ejb/ejb-full-container/src/main/java/org/glassfish/ejb/persistent/timer/PersistentEJBTimerService.java @@ -321,7 +321,7 @@ private boolean getDBReadBeforeTimeoutProperty() { try{ String str=System.getProperty( strDBReadBeforeTimeout ); if( null != str) { - performDBReadBeforeTimeout = Boolean.valueOf(str).booleanValue(); + performDBReadBeforeTimeout = Boolean.parseBoolean(str); if( logger.isLoggable(Level.FINE) ) { logger.log(Level.FINE, "EJB Timer Service property : " + @@ -1390,8 +1390,7 @@ private static boolean deployEJBTimerService(File root, File appScratchFile, logger.log (Level.INFO, "Loading EJBTimerService. Please wait."); File app = null; try { - app = FileUtils.getManagedFile(TIMER_SERVICE_APP_NAME + ".war", - new File(root, "lib/install/applications/")); + app = FileUtils.copyResource(root, "lib", "install", "applications", TIMER_SERVICE_APP_NAME + ".war"); } catch (Exception e) { logger.log (Level.WARNING, "Caught unexpected exception", e); } diff --git a/appserver/webservices/metro-glue/src/main/java/org/glassfish/webservices/metroglue/MetroContainer.java b/appserver/webservices/metro-glue/src/main/java/org/glassfish/webservices/metroglue/MetroContainer.java index 45429ae92d3..c73c2f2ff8c 100644 --- a/appserver/webservices/metro-glue/src/main/java/org/glassfish/webservices/metroglue/MetroContainer.java +++ b/appserver/webservices/metro-glue/src/main/java/org/glassfish/webservices/metroglue/MetroContainer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Contributors to the Eclipse Foundation + * Copyright (c) 2022, 2023 Contributors to the Eclipse Foundation * Copyright (c) 2011, 2018 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the @@ -75,7 +75,6 @@ public class MetroContainer implements PostConstruct, Container, WebServiceDeplo private static final ResourceBundle rb = logger.getResourceBundle(); // private static final String WSTX_SERVICES_APP_NAME = "wstx-services"; - private static final String METRO_APPS_INSTALL_ROOT = "lib/install/applications/metro"; private static final Object lock = new Object(); private final AtomicBoolean wstxServicesDeployed = new AtomicBoolean(false); private final AtomicBoolean wstxServicesDeploying = new AtomicBoolean(false); @@ -169,7 +168,8 @@ public void deployWsTxServices(String target) { File root = serverContext.getInstallRoot(); File app = null; try { - app = FileUtils.getManagedFile(WSTX_SERVICES_APP_NAME + ".war", new File(root, METRO_APPS_INSTALL_ROOT)); + app = FileUtils.copyResource(root, "lib", "install", "applications", "metro", + WSTX_SERVICES_APP_NAME + ".war"); } catch (Exception e) { logger.log(Level.WARNING, LogUtils.WSTX_SERVICE_UNEXPECTED_EXCEPTION, e); } @@ -238,7 +238,7 @@ private boolean isCluster() { private boolean isHaEnabled() { boolean haEnabled = false; if (availabilityService != null) { - haEnabled = Boolean.valueOf(availabilityService.getAvailabilityEnabled()); + haEnabled = Boolean.parseBoolean(availabilityService.getAvailabilityEnabled()); } // if (haEnabled) { diff --git a/nucleus/admin/cli/src/main/java/com/sun/enterprise/admin/cli/embeddable/DeployerImpl.java b/nucleus/admin/cli/src/main/java/com/sun/enterprise/admin/cli/embeddable/DeployerImpl.java index 9a0cc9ece63..09285784603 100644 --- a/nucleus/admin/cli/src/main/java/com/sun/enterprise/admin/cli/embeddable/DeployerImpl.java +++ b/nucleus/admin/cli/src/main/java/com/sun/enterprise/admin/cli/embeddable/DeployerImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Contributors to the Eclipse Foundation + * Copyright (c) 2022, 2023 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 @@ -125,6 +125,13 @@ public String deploy(InputStream is, String... params) throws GlassFishException return deploy(createFile(is), params); } catch (IOException e) { throw new GlassFishException(e); + } finally { + try { + // Declared in the javadoc + is.close(); + } catch (IOException e) { + throw new IllegalStateException("Could not close the input stream!", e); + } } } @@ -157,26 +164,18 @@ public Collection getDeployedApplications() throws GlassFishException { } private File convertToFile(URI archive) throws IOException { - File file; if ("file".equalsIgnoreCase(archive.getScheme())) { - file = new File(archive); - } else { - file = createFile(archive.toURL().openStream()); + return new File(archive); + } + try (InputStream openStream = archive.toURL().openStream()) { + return createFile(openStream); } - return file; } private File createFile(InputStream in) throws IOException { - File file; - file = File.createTempFile("app", "tmp"); + File file = File.createTempFile("app", "tmp"); file.deleteOnExit(); - try (FileOutputStream out = new FileOutputStream(file)) { - FileUtils.copy(in, out); - } finally { - if (in != null) { - in.close(); - } - } + FileUtils.copy(in, file); return file; } @@ -190,10 +189,7 @@ private File createFile(InputStream in) throws IOException { private void extractPayload(Payload.Outbound outboundPayload, ActionReport actionReport, File retrieveDir) { File payloadZip = null; try { - /* - * Add the report to the payload to mimic what the normal - * non-embedded server does. - */ + // Add the report to the payload to mimic what the normal non-embedded server does. final ByteArrayOutputStream baos = new ByteArrayOutputStream(1024); actionReport.writeReport(baos); final ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); @@ -201,26 +197,22 @@ private void extractPayload(Payload.Outbound outboundPayload, ActionReport actio reportProps.setProperty("data-request-type", "report"); outboundPayload.addPart(0, actionReport.getContentType(), "report", reportProps, bais); - /* - * Now process the payload as an *inbound* payload as the non-embedded - * admin client does, by writing the *outbound* payload to a temporary file - * then reading from that file. - */ + // Now process the payload as an *inbound* payload as the non-embedded + // admin client does, by writing the *outbound* payload to a temporary file + // then reading from that file. payloadZip = File.createTempFile("appclient", ".zip"); try (FileOutputStream payloadOutputStream = new FileOutputStream(payloadZip)) { outboundPayload.writeTo(payloadOutputStream); } - /* - * Use the temp file's contents as the inbound payload to - * correctly process the downloaded files. - */ + + // Use the temp file's contents as the inbound payload to + // correctly process the downloaded files. final PayloadFilesManager pfm = new PayloadFilesManager.Perm(retrieveDir, null, logger); try (FileInputStream payloadInputStream = new FileInputStream(payloadZip)) { PayloadImpl.Inbound inboundPayload = PayloadImpl.Inbound.newInstance("application/zip", payloadInputStream); pfm.processParts(inboundPayload); // explodes the payloadZip. } } catch (Exception ex) { - // Log error and ignore exception. logger.log(Level.WARNING, ex.getMessage(), ex); } finally { if (payloadZip != null) { diff --git a/nucleus/admin/launcher/src/main/java/com/sun/enterprise/admin/launcher/GFLauncher.java b/nucleus/admin/launcher/src/main/java/com/sun/enterprise/admin/launcher/GFLauncher.java index 86c4ec4873a..c0f286bc354 100644 --- a/nucleus/admin/launcher/src/main/java/com/sun/enterprise/admin/launcher/GFLauncher.java +++ b/nucleus/admin/launcher/src/main/java/com/sun/enterprise/admin/launcher/GFLauncher.java @@ -34,6 +34,7 @@ import java.io.OutputStreamWriter; import java.nio.file.Files; import java.nio.file.Path; +import java.nio.file.StandardCopyOption; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; @@ -430,7 +431,7 @@ public final boolean needsManualUpgrade() { abstract void internalLaunch() throws GFLauncherException; - void launchInstance() throws GFLauncherException, MiniXmlParserException { + void launchInstance() throws GFLauncherException { if (isFakeLaunch()) { return; } @@ -947,7 +948,7 @@ private void setupUpgradeSecurity() throws GFLauncherException { Path source = callerParameters.installDir.toPath().resolve(Path.of("lib", "templates", "server.policy")); Path target = callerParameters.getConfigDir().toPath().resolve("server.policy"); try { - Files.copy(source, target); + Files.copy(source, target, StandardCopyOption.REPLACE_EXISTING); } catch (IOException ioe) { // the actual error is wrapped differently depending on // whether the problem was with the source or target @@ -969,10 +970,10 @@ private void renameOsgiCache() throws GFLauncherException { File osgiCacheDir = new File(callerParameters.getDomainRootDir(), "osgi-cache"); File backupOsgiCacheDir = new File(callerParameters.getDomainRootDir(), "osgi-cache-" + System.currentTimeMillis()); if (osgiCacheDir.exists() && !backupOsgiCacheDir.exists()) { - if (!FileUtils.renameFile(osgiCacheDir, backupOsgiCacheDir)) { - throw new GFLauncherException(strings.get("rename_osgi_cache_failed", osgiCacheDir, backupOsgiCacheDir)); - } else { + if (FileUtils.renameFile(osgiCacheDir, backupOsgiCacheDir)) { GFLauncherLogger.fine("rename_osgi_cache_succeeded", osgiCacheDir, backupOsgiCacheDir); + } else { + throw new GFLauncherException(strings.get("rename_osgi_cache_failed", osgiCacheDir, backupOsgiCacheDir)); } } } diff --git a/nucleus/admin/rest/rest-service/src/main/java/org/glassfish/admin/rest/resources/StatusGenerator.java b/nucleus/admin/rest/rest-service/src/main/java/org/glassfish/admin/rest/resources/StatusGenerator.java index a5a5e76f0ce..317fb4d6651 100644 --- a/nucleus/admin/rest/rest-service/src/main/java/org/glassfish/admin/rest/resources/StatusGenerator.java +++ b/nucleus/admin/rest/rest-service/src/main/java/org/glassfish/admin/rest/resources/StatusGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Contributors to the Eclipse Foundation + * Copyright (c) 2022, 2023 Contributors to the Eclipse Foundation * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the @@ -72,7 +72,7 @@ @Path("/status/") public class StatusGenerator extends AbstractResource { - // FIXME: Wouldn't be better to send it to the client? + // FIXME: Wouldn't be better to send messages to the client? private static final File FILE = new File(FileUtils.USER_HOME, "GlassFishI18NData.properties"); private final Set commandsUsed = new TreeSet<>(); diff --git a/nucleus/admin/util/src/main/java/com/sun/enterprise/admin/remote/RemoteResponseManager.java b/nucleus/admin/util/src/main/java/com/sun/enterprise/admin/remote/RemoteResponseManager.java index b0b8c7f2f90..42c730c231e 100644 --- a/nucleus/admin/util/src/main/java/com/sun/enterprise/admin/remote/RemoteResponseManager.java +++ b/nucleus/admin/util/src/main/java/com/sun/enterprise/admin/remote/RemoteResponseManager.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Contributors to the Eclipse Foundation + * Copyright (c) 2022, 2023 Contributors to the Eclipse Foundation * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the diff --git a/nucleus/admin/util/src/main/java/com/sun/enterprise/admin/remote/reader/ActionReportJsonProprietaryReader.java b/nucleus/admin/util/src/main/java/com/sun/enterprise/admin/remote/reader/ActionReportJsonProprietaryReader.java index 7658e4d4f56..f4ee2c57d31 100644 --- a/nucleus/admin/util/src/main/java/com/sun/enterprise/admin/remote/reader/ActionReportJsonProprietaryReader.java +++ b/nucleus/admin/util/src/main/java/com/sun/enterprise/admin/remote/reader/ActionReportJsonProprietaryReader.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Contributors to the Eclipse Foundation + * Copyright (c) 2022, 2023 Contributors to the Eclipse Foundation * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the diff --git a/nucleus/admin/util/src/main/java/com/sun/enterprise/admin/remote/reader/AdminCommandStateJsonProprietaryReader.java b/nucleus/admin/util/src/main/java/com/sun/enterprise/admin/remote/reader/AdminCommandStateJsonProprietaryReader.java index 4706bb76b12..f0775db23e4 100644 --- a/nucleus/admin/util/src/main/java/com/sun/enterprise/admin/remote/reader/AdminCommandStateJsonProprietaryReader.java +++ b/nucleus/admin/util/src/main/java/com/sun/enterprise/admin/remote/reader/AdminCommandStateJsonProprietaryReader.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Contributors to the Eclipse Foundation + * Copyright (c) 2022, 2023 Contributors to the Eclipse Foundation * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the diff --git a/nucleus/admin/util/src/main/java/com/sun/enterprise/admin/remote/reader/ParamsWithPayloadJsonProprietaryReader.java b/nucleus/admin/util/src/main/java/com/sun/enterprise/admin/remote/reader/ParamsWithPayloadJsonProprietaryReader.java index 1e114b46e98..c315a7af41a 100644 --- a/nucleus/admin/util/src/main/java/com/sun/enterprise/admin/remote/reader/ParamsWithPayloadJsonProprietaryReader.java +++ b/nucleus/admin/util/src/main/java/com/sun/enterprise/admin/remote/reader/ParamsWithPayloadJsonProprietaryReader.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Contributors to the Eclipse Foundation + * Copyright (c) 2022, 2023 Contributors to the Eclipse Foundation * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the diff --git a/nucleus/admin/util/src/main/java/com/sun/enterprise/admin/remote/reader/ProgressStatusDTOJsonProprietaryReader.java b/nucleus/admin/util/src/main/java/com/sun/enterprise/admin/remote/reader/ProgressStatusDTOJsonProprietaryReader.java index eee6c6f4ac4..bb17592457f 100644 --- a/nucleus/admin/util/src/main/java/com/sun/enterprise/admin/remote/reader/ProgressStatusDTOJsonProprietaryReader.java +++ b/nucleus/admin/util/src/main/java/com/sun/enterprise/admin/remote/reader/ProgressStatusDTOJsonProprietaryReader.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Contributors to the Eclipse Foundation + * Copyright (c) 2022, 2023 Contributors to the Eclipse Foundation * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the diff --git a/nucleus/admin/util/src/main/java/com/sun/enterprise/admin/remote/reader/ProgressStatusEventJsonProprietaryReader.java b/nucleus/admin/util/src/main/java/com/sun/enterprise/admin/remote/reader/ProgressStatusEventJsonProprietaryReader.java index 0ee0879bda1..416b7e4718b 100644 --- a/nucleus/admin/util/src/main/java/com/sun/enterprise/admin/remote/reader/ProgressStatusEventJsonProprietaryReader.java +++ b/nucleus/admin/util/src/main/java/com/sun/enterprise/admin/remote/reader/ProgressStatusEventJsonProprietaryReader.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Contributors to the Eclipse Foundation + * Copyright (c) 2022, 2023 Contributors to the Eclipse Foundation * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the diff --git a/nucleus/admin/util/src/main/java/com/sun/enterprise/admin/remote/reader/StringProprietaryReader.java b/nucleus/admin/util/src/main/java/com/sun/enterprise/admin/remote/reader/StringProprietaryReader.java index 59470039e7a..730a2f9ed76 100644 --- a/nucleus/admin/util/src/main/java/com/sun/enterprise/admin/remote/reader/StringProprietaryReader.java +++ b/nucleus/admin/util/src/main/java/com/sun/enterprise/admin/remote/reader/StringProprietaryReader.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Contributors to the Eclipse Foundation + * Copyright (c) 2022, 2023 Contributors to the Eclipse Foundation * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the @@ -41,15 +41,10 @@ public String readFrom(final HttpURLConnection urlConnection) throws IOException public String readFrom(final InputStream is, final String contentType) throws IOException { ByteArrayOutputStream baos = new ByteArrayOutputStream(); try { - byte[] buff = new byte[512]; - int count; - while ((count = is.read(buff)) > 0) { - baos.write(buff, 0, count); - } + is.transferTo(baos); } finally { is.close(); } return baos.toString(StandardCharsets.UTF_8); } - } diff --git a/nucleus/cluster/admin/src/main/java/com/sun/enterprise/v3/admin/cluster/CreateNodeSshCommand.java b/nucleus/cluster/admin/src/main/java/com/sun/enterprise/v3/admin/cluster/CreateNodeSshCommand.java index 4edf4c56ef5..f25e5cef5dd 100644 --- a/nucleus/cluster/admin/src/main/java/com/sun/enterprise/v3/admin/cluster/CreateNodeSshCommand.java +++ b/nucleus/cluster/admin/src/main/java/com/sun/enterprise/v3/admin/cluster/CreateNodeSshCommand.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Contributors to the Eclipse Foundation + * Copyright (c) 2022, 2023 Contributors to the Eclipse Foundation * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the diff --git a/nucleus/cluster/admin/src/main/java/com/sun/enterprise/v3/admin/cluster/SecureAdminBootstrapHelper.java b/nucleus/cluster/admin/src/main/java/com/sun/enterprise/v3/admin/cluster/SecureAdminBootstrapHelper.java index e4a123ffc69..e2a6765b933 100644 --- a/nucleus/cluster/admin/src/main/java/com/sun/enterprise/v3/admin/cluster/SecureAdminBootstrapHelper.java +++ b/nucleus/cluster/admin/src/main/java/com/sun/enterprise/v3/admin/cluster/SecureAdminBootstrapHelper.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Contributors to the Eclipse Foundation + * Copyright (c) 2022, 2023 Contributors to the Eclipse Foundation * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the @@ -21,6 +21,7 @@ import com.jcraft.jsch.SftpException; import com.sun.enterprise.config.serverbeans.Node; import com.sun.enterprise.util.cluster.RemoteType; +import com.sun.enterprise.util.io.FileUtils; import java.io.BufferedInputStream; import java.io.File; @@ -29,7 +30,6 @@ import java.io.IOException; import java.io.InputStream; import java.net.URI; -import java.nio.file.Files; import java.util.logging.Level; import java.util.logging.Logger; @@ -398,7 +398,7 @@ public void copyBootstrapFiles() throws IOException { for (String relativePathToFile : SECURE_ADMIN_FILE_REL_URIS_TO_COPY) { final File origin = new File(existingInstanceDirURI.resolve(relativePathToFile)); final File dest = new File(newInstanceDirURI.resolve(relativePathToFile)); - Files.copy(origin.toPath(), dest.toPath()); + FileUtils.copy(origin, dest); } } diff --git a/nucleus/cluster/admin/src/main/java/com/sun/enterprise/v3/admin/cluster/SetupSshCommand.java b/nucleus/cluster/admin/src/main/java/com/sun/enterprise/v3/admin/cluster/SetupSshCommand.java index 5f240629cc7..5fdeec04c95 100644 --- a/nucleus/cluster/admin/src/main/java/com/sun/enterprise/v3/admin/cluster/SetupSshCommand.java +++ b/nucleus/cluster/admin/src/main/java/com/sun/enterprise/v3/admin/cluster/SetupSshCommand.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Contributors to the Eclipse Foundation + * Copyright (c) 2022, 2023 Contributors to the Eclipse Foundation * Copyright (c) 2011, 2018 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the diff --git a/nucleus/cluster/cli/src/main/java/com/sun/enterprise/admin/cli/cluster/InstallNodeSshCommand.java b/nucleus/cluster/cli/src/main/java/com/sun/enterprise/admin/cli/cluster/InstallNodeSshCommand.java index f88b2cb6553..58e403617c0 100644 --- a/nucleus/cluster/cli/src/main/java/com/sun/enterprise/admin/cli/cluster/InstallNodeSshCommand.java +++ b/nucleus/cluster/cli/src/main/java/com/sun/enterprise/admin/cli/cluster/InstallNodeSshCommand.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Contributors to the Eclipse Foundation + * Copyright (c) 2022, 2023 Contributors to the Eclipse Foundation * Copyright (c) 2011, 2018 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the diff --git a/nucleus/cluster/cli/src/main/java/com/sun/enterprise/admin/cli/cluster/NativeRemoteCommandsBase.java b/nucleus/cluster/cli/src/main/java/com/sun/enterprise/admin/cli/cluster/NativeRemoteCommandsBase.java index 6949c426cae..35ac1d8c202 100644 --- a/nucleus/cluster/cli/src/main/java/com/sun/enterprise/admin/cli/cluster/NativeRemoteCommandsBase.java +++ b/nucleus/cluster/cli/src/main/java/com/sun/enterprise/admin/cli/cluster/NativeRemoteCommandsBase.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Contributors to the Eclipse Foundation + * Copyright (c) 2022, 2023 Contributors to the Eclipse Foundation * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the diff --git a/nucleus/cluster/cli/src/main/java/com/sun/enterprise/admin/cli/cluster/SynchronizeInstanceCommand.java b/nucleus/cluster/cli/src/main/java/com/sun/enterprise/admin/cli/cluster/SynchronizeInstanceCommand.java index 5a26a97d34a..ec3c00aa858 100644 --- a/nucleus/cluster/cli/src/main/java/com/sun/enterprise/admin/cli/cluster/SynchronizeInstanceCommand.java +++ b/nucleus/cluster/cli/src/main/java/com/sun/enterprise/admin/cli/cluster/SynchronizeInstanceCommand.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Contributors to the Eclipse Foundation + * Copyright (c) 2022, 2023 Contributors to the Eclipse Foundation * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the diff --git a/nucleus/cluster/cli/src/main/java/com/sun/enterprise/admin/cli/cluster/UninstallNodeSshCommand.java b/nucleus/cluster/cli/src/main/java/com/sun/enterprise/admin/cli/cluster/UninstallNodeSshCommand.java index 345937f7922..dc8e930aa94 100644 --- a/nucleus/cluster/cli/src/main/java/com/sun/enterprise/admin/cli/cluster/UninstallNodeSshCommand.java +++ b/nucleus/cluster/cli/src/main/java/com/sun/enterprise/admin/cli/cluster/UninstallNodeSshCommand.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Contributors to the Eclipse Foundation + * Copyright (c) 2022, 2023 Contributors to the Eclipse Foundation * Copyright (c) 2011, 2018 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the diff --git a/nucleus/cluster/ssh/src/main/java/org/glassfish/cluster/ssh/util/SSHUtil.java b/nucleus/cluster/ssh/src/main/java/org/glassfish/cluster/ssh/util/SSHUtil.java index 05785fbad72..2facc3a0bea 100644 --- a/nucleus/cluster/ssh/src/main/java/org/glassfish/cluster/ssh/util/SSHUtil.java +++ b/nucleus/cluster/ssh/src/main/java/org/glassfish/cluster/ssh/util/SSHUtil.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Contributors to the Eclipse Foundation + * Copyright (c) 2022, 2023 Contributors to the Eclipse Foundation * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the diff --git a/nucleus/common/amx-core/src/main/java/org/glassfish/admin/amx/util/AMXDebug.java b/nucleus/common/amx-core/src/main/java/org/glassfish/admin/amx/util/AMXDebug.java index 92df4e62856..706232444bc 100644 --- a/nucleus/common/amx-core/src/main/java/org/glassfish/admin/amx/util/AMXDebug.java +++ b/nucleus/common/amx-core/src/main/java/org/glassfish/admin/amx/util/AMXDebug.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Contributors to the Eclipse Foundation + * Copyright (c) 2022, 2023 Contributors to the Eclipse Foundation * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the @@ -260,7 +260,7 @@ private File getDir() if (value == null) { final String instanceRoot = System.getProperty("com.sun.aas.instanceRoot"); - File parentDir = instanceRoot != null ? new File(instanceRoot) : FileUtils.USER_HOME; + File parentDir = instanceRoot == null ? FileUtils.USER_HOME : new File(instanceRoot); debugDir = new File(parentDir, AMX_DEBUG_SUBDIR); } else diff --git a/nucleus/common/common-util/src/main/java/com/sun/enterprise/universal/io/SmartFile.java b/nucleus/common/common-util/src/main/java/com/sun/enterprise/universal/io/SmartFile.java index 89ac60facd9..1ffd8e55b3d 100644 --- a/nucleus/common/common-util/src/main/java/com/sun/enterprise/universal/io/SmartFile.java +++ b/nucleus/common/common-util/src/main/java/com/sun/enterprise/universal/io/SmartFile.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Contributors to the Eclipse Foundation + * Copyright (c) 2022, 2023 Contributors to the Eclipse Foundation * Copyright (c) 2008, 2018 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the diff --git a/nucleus/common/common-util/src/main/java/com/sun/enterprise/util/io/FileUtils.java b/nucleus/common/common-util/src/main/java/com/sun/enterprise/util/io/FileUtils.java index 3b89d8b9c71..57b747676e1 100644 --- a/nucleus/common/common-util/src/main/java/com/sun/enterprise/util/io/FileUtils.java +++ b/nucleus/common/common-util/src/main/java/com/sun/enterprise/util/io/FileUtils.java @@ -24,6 +24,7 @@ import java.io.BufferedReader; import java.io.File; import java.io.FileFilter; +import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.FileReader; import java.io.FilenameFilter; @@ -40,6 +41,7 @@ import java.nio.channels.ReadableByteChannel; import java.nio.channels.WritableByteChannel; import java.nio.file.Files; +import java.nio.file.Path; import java.nio.file.StandardCopyOption; import java.util.Collection; import java.util.Locale; @@ -612,14 +614,14 @@ private static File relativize(File parent, File child) { * @param work the RetriableWork implementation to be run * @return the number of retries performed; 0 indicates the work succeeded without having to * retry - * @deprecated The situation usually means there's an IO leak. It can be used also on Windows OS - * when many threads are trying to access the same file. + * @deprecated The situation usually means there's an IO leak. The only practical usage is + * on Windows OS when many threads/processes are trying to access the same file. */ @Deprecated private static int doWithRetry(RetriableWork work) { int retries = 0; - // Try the work the first time. Ideally this will work. + // Try the work the first time. Ideally this will work. work.run(); // If the work failed and this is Windows - on which running gc may @@ -741,6 +743,20 @@ static boolean isValidString(String s) { return s != null && !s.isEmpty(); } + /** + * This method should be used instead of {@link #copy(InputStream, File, long)} if you don't + * know the size of the input stream. + * + * @param in It will NOT be closed after processing. That is caller's responsibility. + * @param out Target output file. If the file already exists, it will be overwritten! + * @throws IOException + */ + public static void copy(File in, OutputStream out) throws IOException { + try (FileInputStream input = new FileInputStream(in)) { + input.transferTo(out); + } + } + /** * Fast method using NIO to copy data from the input to the output file, when you already do @@ -852,7 +868,8 @@ public static boolean renameFile(File fromFile, File toFile) { * file to be read is small . * * @param file Absolute path of the file - * @return String representing the contents of the file, empty String for an empty file + * @return String representing the contents of the file. Lines are separated by + * {@link System#lineSeparator()}. * @throws java.io.IOException if there is an i/o error. * @throws java.io.FileNotFoundException if the file could not be found */ @@ -872,33 +889,28 @@ public static String readSmallFile(final File file) throws IOException { /** * If the path dir/file does not exist, look for it in the classpath. * If found in classpath, create dir/file. + *

+ * Existing file will not be overwritten. * - * @param file - path to look for - * @param dir - directory where the path file should exist + * @param dir - directory where the path file should exist (including resource path) + * @param resourcePath - resource loadable by the thread context classloader. * @return the File representing dir/file. If that does not exist, return null. * @throws IOException */ - public static File getManagedFile(String file, File dir) throws IOException { - File f = new File(dir, file); + public static File copyResource(File dir, String... resourcePath) throws IOException { + File f = new File(dir, String.join(File.separator, resourcePath)); if (f.exists()) { return f; } - try (InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream(file)) { + try (InputStream is = Thread.currentThread().getContextClassLoader() + .getResourceAsStream(String.join("/", resourcePath))) { if (is == null) { return null; } - try (InputStream bis = new BufferedInputStream(is)) { - if (!mkdirsMaybe(f.getParentFile())) { - throw new IOException("Can't create parent dir of output file: " + f); - } - try (OutputStream os = new BufferedOutputStream(FileUtils.openFileOutputStream(f))) { - byte buf[] = new byte[10240]; - int len = 0; - while ((len = bis.read(buf)) > 0) { - os.write(buf, 0, len); - } - } + if (!mkdirsMaybe(f.getParentFile())) { + throw new IOException("Can't create parent dir of output file: " + f); } + copy(is, f); return f; } } diff --git a/nucleus/common/common-util/src/main/java/com/sun/enterprise/util/zip/ZipFile.java b/nucleus/common/common-util/src/main/java/com/sun/enterprise/util/zip/ZipFile.java index abac13577f6..1d62417c3d4 100644 --- a/nucleus/common/common-util/src/main/java/com/sun/enterprise/util/zip/ZipFile.java +++ b/nucleus/common/common-util/src/main/java/com/sun/enterprise/util/zip/ZipFile.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2022 Contributors to the Eclipse Foundation + * Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the @@ -139,11 +139,8 @@ public ArrayList explode() throws ZipFileException { bos = new BufferedOutputStream(getOutputStream(f), BUFFER_SIZE); - int totalBytes = 0; - for (int numBytes = zin.read(buffer); numBytes > 0; numBytes = zin.read(buffer)) { bos.write(buffer, 0, numBytes); - totalBytes += numBytes; } bos.close(); bos = null; diff --git a/nucleus/common/common-util/src/test/java/com/sun/enterprise/util/io/FileUtilsTest.java b/nucleus/common/common-util/src/test/java/com/sun/enterprise/util/io/FileUtilsTest.java index a10c1930226..48209c91e7e 100644 --- a/nucleus/common/common-util/src/test/java/com/sun/enterprise/util/io/FileUtilsTest.java +++ b/nucleus/common/common-util/src/test/java/com/sun/enterprise/util/io/FileUtilsTest.java @@ -64,6 +64,17 @@ public void testMkdirsMaybe() { } + @Test + public void testCopyFileToStream() throws Exception { + File outputFile = new File(tempDir, "outputFile"); + File testFile = new File(FileUtilsTest.class.getResource("/adminport.xml").toURI()); + try (FileOutputStream os = new FileOutputStream(outputFile)) { + FileUtils.copy(testFile, os); + } + assertEquals(testFile.length(), outputFile.length()); + } + + @Test public void testCopyFiles() throws Exception { File outputFile = new File(tempDir, "outputFile"); diff --git a/nucleus/common/glassfish-api/src/main/java/org/glassfish/api/deployment/archive/ReadableArchiveAdapter.java b/nucleus/common/glassfish-api/src/main/java/org/glassfish/api/deployment/archive/ReadableArchiveAdapter.java index c4e64e9c84c..7783e918fc4 100644 --- a/nucleus/common/glassfish-api/src/main/java/org/glassfish/api/deployment/archive/ReadableArchiveAdapter.java +++ b/nucleus/common/glassfish-api/src/main/java/org/glassfish/api/deployment/archive/ReadableArchiveAdapter.java @@ -1,4 +1,5 @@ /* + * Copyright (c) 2023 Contributors to the Eclipse Foundation * Copyright (c) 2008, 2018 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the @@ -27,12 +28,7 @@ * * @author Byron Nevins */ -abstract public class ReadableArchiveAdapter implements ReadableArchive { - - @Override - public long getEntrySize(String arg0) { - return 0L; - } +public abstract class ReadableArchiveAdapter implements ReadableArchive { @Override public void open(URI arg0) throws IOException { diff --git a/nucleus/common/internal-api/src/main/java/org/glassfish/internal/deployment/GenericHandler.java b/nucleus/common/internal-api/src/main/java/org/glassfish/internal/deployment/GenericHandler.java index 0d9155cf7ac..4c85698ee3f 100644 --- a/nucleus/common/internal-api/src/main/java/org/glassfish/internal/deployment/GenericHandler.java +++ b/nucleus/common/internal-api/src/main/java/org/glassfish/internal/deployment/GenericHandler.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Contributors to the Eclipse Foundation + * Copyright (c) 2022, 2023 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 diff --git a/nucleus/common/simple-glassfish-api/src/main/java/org/glassfish/embeddable/Deployer.java b/nucleus/common/simple-glassfish-api/src/main/java/org/glassfish/embeddable/Deployer.java index d07de2ffbce..1fddde2ea25 100644 --- a/nucleus/common/simple-glassfish-api/src/main/java/org/glassfish/embeddable/Deployer.java +++ b/nucleus/common/simple-glassfish-api/src/main/java/org/glassfish/embeddable/Deployer.java @@ -1,4 +1,5 @@ /* + * Copyright (c) 2023 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 @@ -20,7 +21,6 @@ import java.io.InputStream; import java.net.URI; import java.util.Collection; -import java.util.Map; /** * Deployer service for GlassFish. Using this service, one can deploy and undeploy applications. diff --git a/nucleus/core/kernel/src/main/java/com/sun/enterprise/v3/server/ApplicationLifecycle.java b/nucleus/core/kernel/src/main/java/com/sun/enterprise/v3/server/ApplicationLifecycle.java index a919296066d..f8f6db7a9ff 100644 --- a/nucleus/core/kernel/src/main/java/com/sun/enterprise/v3/server/ApplicationLifecycle.java +++ b/nucleus/core/kernel/src/main/java/com/sun/enterprise/v3/server/ApplicationLifecycle.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2022 Contributors to the Eclipse Foundation. + * Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation. * Copyright (c) 2008, 2018 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the @@ -30,16 +30,15 @@ import com.sun.enterprise.config.serverbeans.ServerTags; import com.sun.enterprise.deploy.shared.ArchiveFactory; import com.sun.enterprise.util.LocalStringManagerImpl; +import com.sun.enterprise.util.io.FileUtils; import jakarta.inject.Inject; import jakarta.inject.Named; import jakarta.inject.Singleton; import java.beans.PropertyVetoException; -import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.File; -import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; @@ -1967,7 +1966,6 @@ private void prepareGeneratedContent(final DeploymentContext dc, final Parameter */ final File generatedContentZip = createGeneratedContentZip(); - ZipOutputStream zipOS = null; /* * We want the ZIP file to contain xml/(appname), ejb/(appname), etc. directories, even if those directories don't @@ -1976,16 +1974,26 @@ private void prepareGeneratedContent(final DeploymentContext dc, final Parameter */ final File baseDir = dc.getScratchDir("xml").getParentFile().getParentFile(); - for (String scratchType : UPLOADED_GENERATED_DIRS) { - - zipOS = addScratchContentIfPresent(dc, baseDir, zipOS, generatedContentZip, scratchType); + ZipOutputStream zipOS = null; + try { + for (String scratchType : UPLOADED_GENERATED_DIRS) { + final File genDir = dc.getScratchDir(scratchType); + if (genDir.isDirectory()) { + if (zipOS == null) { + zipOS = new ZipOutputStream( + new BufferedOutputStream(new FileOutputStream(generatedContentZip))); + } + addFileToZip(zipOS, baseDir, genDir); + } + } + } finally { + if (zipOS != null) { + zipOS.close(); + } } if (zipOS != null) { - /* - * Because we did zip up some generated content, add the just-generated zip file as a parameter to the param map. - */ - zipOS.close(); + // Because we did zip up some generated content, add the just-generated zip file as a parameter to the param map. // set the generated content param paramMap.set("generatedcontent", generatedContentZip.getAbsolutePath()); } @@ -1997,18 +2005,6 @@ private File createGeneratedContentZip() throws IOException { return tempFile; } - private ZipOutputStream addScratchContentIfPresent(final DeploymentContext dc, final File baseDir, ZipOutputStream zipOS, - final File generatedContentZip, final String scratchDirName) throws IOException { - final File genDir = dc.getScratchDir(scratchDirName); - if (genDir.isDirectory()) { - if (zipOS == null) { - zipOS = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(generatedContentZip))); - } - addFileToZip(zipOS, baseDir, genDir); - } - return zipOS; - } - private void addFileToZip(final ZipOutputStream zipOS, final File baseDir, final File f) throws IOException { final String entryName = baseDir.toURI().relativize(f.toURI()).getPath(); final ZipEntry entry = new ZipEntry(entryName); @@ -2020,15 +2016,8 @@ private void addFileToZip(final ZipOutputStream zipOS, final File baseDir, final addFileToZip(zipOS, baseDir, subFile); } } else { - final byte[] buffer = new byte[1024]; - try (final InputStream is = new BufferedInputStream(new FileInputStream(f))) { - int bytesRead; - while ((bytesRead = is.read(buffer)) != -1) { - zipOS.write(buffer, 0, bytesRead); - } - } finally { - zipOS.closeEntry(); - } + FileUtils.copy(f, zipOS); + zipOS.closeEntry(); } } diff --git a/nucleus/deployment/admin/src/main/java/org/glassfish/deployment/admin/DeployCommand.java b/nucleus/deployment/admin/src/main/java/org/glassfish/deployment/admin/DeployCommand.java index a0d3ecd42d0..cffc99ff6e3 100644 --- a/nucleus/deployment/admin/src/main/java/org/glassfish/deployment/admin/DeployCommand.java +++ b/nucleus/deployment/admin/src/main/java/org/glassfish/deployment/admin/DeployCommand.java @@ -359,8 +359,10 @@ public void execute(AdminCommandContext context) { File existrepos = new File(new URI(app.getLocation())); String appname = app.getName(); if (!appname.equals(name) && existrepos.getAbsoluteFile().equals(reposDir.getAbsoluteFile())) { - report.failure(logger, localStrings.getLocalString("deploy.dupdeployment", - "Application {0} is trying to use the same repository directory as application {1}, please choose a different application name to deploy", + report.failure(logger, + localStrings.getLocalString("deploy.dupdeployment", + "Application {0} is trying to use the same repository directory as application {1}," + + " please choose a different application name to deploy", name, appname)); return; } diff --git a/nucleus/deployment/common/src/main/java/com/sun/enterprise/deploy/shared/FileArchive.java b/nucleus/deployment/common/src/main/java/com/sun/enterprise/deploy/shared/FileArchive.java index 41b46dcf1db..85d40073bd5 100644 --- a/nucleus/deployment/common/src/main/java/com/sun/enterprise/deploy/shared/FileArchive.java +++ b/nucleus/deployment/common/src/main/java/com/sun/enterprise/deploy/shared/FileArchive.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2022 Contributors to the Eclipse Foundation. All rights reserved. + * Copyright (c) 2022, 2023 Contributors to the Eclipse Foundation. All rights reserved. * Copyright (c) 2006, 2018 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the @@ -99,27 +99,21 @@ public class FileArchive extends AbstractReadableArchive implements WritableArch @Inject private ArchiveFactory archiveFactory; - // the archive abstraction directory. + /** the archive abstraction directory. */ private File archive; private URI uri; - /* - * tracks stale files in the archive and filters the archive's contents to exclude stale entries + /** + * Tracks stale files in the archive and filters the archive's contents to exclude stale entries */ private StaleFileManager staleFileManager; - /* - * Records whether open or create has been invoked. Otherwise we can't be sure that the staleFileManager field has been - * set. + /** + * Records whether open or create has been invoked. Otherwise we can't be sure that + * the staleFileManager field has been set. */ private boolean isOpenedOrCreated; - /** - * Used just by HK2 - * - * @deprecated - */ - @Deprecated public FileArchive() { } diff --git a/nucleus/deployment/common/src/main/java/org/glassfish/deployment/common/DeploymentContextImpl.java b/nucleus/deployment/common/src/main/java/org/glassfish/deployment/common/DeploymentContextImpl.java index ff3a24b4a53..564f6dc88d4 100644 --- a/nucleus/deployment/common/src/main/java/org/glassfish/deployment/common/DeploymentContextImpl.java +++ b/nucleus/deployment/common/src/main/java/org/glassfish/deployment/common/DeploymentContextImpl.java @@ -247,15 +247,14 @@ public synchronized ClassLoader getClassLoader(boolean sharable) { // we are out of the prepare phase, destroy the shareableTemp and // return the final classloader - if (sharableTemp != null) { + if (sharableTemp instanceof PreDestroy) { try { PreDestroy.class.cast(sharableTemp).preDestroy(); } catch (Exception e) { - // ignore, the classloader does not need to be destroyed + getLogger().log(Level.WARNING, "ClassLoader preDestroy failed for " + sharableTemp, e); } - sharableTemp = null; } - + sharableTemp = null; return cloader; } diff --git a/nucleus/deployment/common/src/main/java/org/glassfish/deployment/common/DeploymentUtils.java b/nucleus/deployment/common/src/main/java/org/glassfish/deployment/common/DeploymentUtils.java index 39c2e72730f..ab8f64b2aea 100644 --- a/nucleus/deployment/common/src/main/java/org/glassfish/deployment/common/DeploymentUtils.java +++ b/nucleus/deployment/common/src/main/java/org/glassfish/deployment/common/DeploymentUtils.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2022 Contributors to the Eclipse Foundation. + * Copyright (c) 2022, 2023 Contributors to the Eclipse Foundation. * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the diff --git a/nucleus/deployment/common/src/main/java/org/glassfish/deployment/common/ModuleExploder.java b/nucleus/deployment/common/src/main/java/org/glassfish/deployment/common/ModuleExploder.java index 4d1a507a337..9da5581d1f4 100644 --- a/nucleus/deployment/common/src/main/java/org/glassfish/deployment/common/ModuleExploder.java +++ b/nucleus/deployment/common/src/main/java/org/glassfish/deployment/common/ModuleExploder.java @@ -1,4 +1,5 @@ /* + * Copyright (c) 2023 Contributors to the Eclipse Foundation * Copyright (c) 2006, 2018 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the diff --git a/nucleus/deployment/common/src/main/java/org/glassfish/deployment/versioning/VersioningService.java b/nucleus/deployment/common/src/main/java/org/glassfish/deployment/versioning/VersioningService.java index 5beebd5008c..907fc2d5ec5 100644 --- a/nucleus/deployment/common/src/main/java/org/glassfish/deployment/versioning/VersioningService.java +++ b/nucleus/deployment/common/src/main/java/org/glassfish/deployment/versioning/VersioningService.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Contributors to the Eclipse Foundation + * Copyright (c) 2022, 2023 Contributors to the Eclipse Foundation * Copyright (c) 2008, 2018 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the @@ -265,20 +265,13 @@ public void handleDisable(final String appName, final String target, * @return the name of the version currently using the directory, else null * @throws VersioningSyntaxException * */ - public String getVersionFromSameDir(File dir) - throws VersioningSyntaxException{ - + public String getVersionFromSameDir(File directory) throws VersioningSyntaxException { try { - Application app = null; - // check if directory deployment exist - for (Application element : domain.getApplications().getApplications()) { - app = element; - /* - * A lifecycle module appears as an application but has a null location. - */ - if (dir.toURI().toString().equals(app.getLocation())) { - if(!VersioningUtils.getUntaggedName(app.getName()).equals(app.getName())){ + for (Application app : domain.getApplications().getApplications()) { + // A lifecycle module appears as an application but has a null location. + if (directory.toURI().toString().equals(app.getLocation())) { + if (!VersioningUtils.getUntaggedName(app.getName()).equals(app.getName())) { return app.getName(); } } diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/common/EmbeddedSecurityLifeCycle.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/common/EmbeddedSecurityLifeCycle.java index 7482f4def0b..afbc9c0b898 100644 --- a/nucleus/security/core/src/main/java/com/sun/enterprise/security/common/EmbeddedSecurityLifeCycle.java +++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/common/EmbeddedSecurityLifeCycle.java @@ -1,4 +1,5 @@ /* + * Copyright (c) 2023 Contributors to the Eclipse Foundation * Copyright (c) 2010, 2021 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the @@ -38,10 +39,8 @@ import jakarta.inject.Named; /** - * * @author Nithya Subramanian */ - @Service public class EmbeddedSecurityLifeCycle implements EmbeddedLifecycle { @@ -70,15 +69,15 @@ public void creation(Server server) { //Get the keyfile names from the security service List keyFileNames = embeddedSecurity.getKeyFileNames(securityService); for (String keyFileName : keyFileNames) { - //Copy the keyfiles in instanceRoot/config. If file is already present, then exit (handled by getManagedFile) - FileUtils.getManagedFile("config" + File.separator + embeddedSecurity.parseFileName(keyFileName), instanceRoot); + // Copy the keyfiles in instanceRoot/config. If file is already present, then exit (handled by getManagedFile) + FileUtils.copyResource(instanceRoot, "config", embeddedSecurity.parseFileName(keyFileName)); } //Copy the other security files to instanceRoot/config //Assuming that these files are present as config/filename in the embedded jar file and are to be extracted that way/ - FileUtils.getManagedFile("config" + File.separator + "login.conf", instanceRoot); - FileUtils.getManagedFile("config" + File.separator + "server.policy", instanceRoot); - FileUtils.getManagedFile("config" + File.separator + "cacerts.jks", instanceRoot); - FileUtils.getManagedFile("config" + File.separator + "keystore.jks", instanceRoot); + FileUtils.copyResource(instanceRoot,"config", "login.conf"); + FileUtils.copyResource(instanceRoot,"config", "server.policy"); + FileUtils.copyResource(instanceRoot,"config", "cacerts.jks"); + FileUtils.copyResource(instanceRoot,"config", "keystore.jks"); String keystoreFile = null; String truststoreFile = null; try { diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/embedded/EmbeddedSecurityUtil.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/embedded/EmbeddedSecurityUtil.java index dffb35827d9..a6b1bda571f 100644 --- a/nucleus/security/core/src/main/java/com/sun/enterprise/security/embedded/EmbeddedSecurityUtil.java +++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/embedded/EmbeddedSecurityUtil.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 Contributors to the Eclipse Foundation + * Copyright (c) 2023 Contributors to the Eclipse Foundation. * Copyright (c) 2010, 2021 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the @@ -22,6 +22,7 @@ import com.sun.enterprise.security.EmbeddedSecurity; import com.sun.enterprise.security.SecurityLoggerInfo; import com.sun.enterprise.util.StringUtils; +import com.sun.enterprise.util.io.FileUtils; import jakarta.inject.Singleton; @@ -29,7 +30,6 @@ import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; -import java.nio.file.Files; import java.util.ArrayList; import java.util.List; import java.util.logging.Level; @@ -110,7 +110,7 @@ public void copyConfigFiles(ServiceLocator habitat, File fromInstanceDir, File d //Copy files into new directory for (String fileName : fileNames) { - Files.copy(new File(fileName).toPath(), new File(toConfigDir, parseFileName(fileName)).toPath()); + FileUtils.copy(new File(fileName), new File(toConfigDir, parseFileName(fileName))); } } catch (IOException e) { _logger.log(Level.WARNING, SecurityLoggerInfo.ioError, e); From e17505ff79cb829122d2070d2b3a65a1b3daefd6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Mat=C4=9Bj=C4=8Dek?= Date: Sun, 8 Oct 2023 03:41:56 +0200 Subject: [PATCH 10/12] Implemented copyResourceToDirectory + fixed usages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: David Matějček --- .../timer/PersistentEJBTimerService.java | 3 +- .../webservices/metroglue/MetroContainer.java | 4 +- .../com/sun/enterprise/util/io/FileUtils.java | 122 ++++++++++-------- .../common/EmbeddedSecurityLifeCycle.java | 11 +- 4 files changed, 75 insertions(+), 65 deletions(-) diff --git a/appserver/ejb/ejb-full-container/src/main/java/org/glassfish/ejb/persistent/timer/PersistentEJBTimerService.java b/appserver/ejb/ejb-full-container/src/main/java/org/glassfish/ejb/persistent/timer/PersistentEJBTimerService.java index 2e74d96967d..78db1f55363 100755 --- a/appserver/ejb/ejb-full-container/src/main/java/org/glassfish/ejb/persistent/timer/PersistentEJBTimerService.java +++ b/appserver/ejb/ejb-full-container/src/main/java/org/glassfish/ejb/persistent/timer/PersistentEJBTimerService.java @@ -1390,7 +1390,8 @@ private static boolean deployEJBTimerService(File root, File appScratchFile, logger.log (Level.INFO, "Loading EJBTimerService. Please wait."); File app = null; try { - app = FileUtils.copyResource(root, "lib", "install", "applications", TIMER_SERVICE_APP_NAME + ".war"); + File outputDir = new File(root, "lib/install/applications"); + app = FileUtils.copyResourceToDirectory(TIMER_SERVICE_APP_NAME + ".war", outputDir); } catch (Exception e) { logger.log (Level.WARNING, "Caught unexpected exception", e); } diff --git a/appserver/webservices/metro-glue/src/main/java/org/glassfish/webservices/metroglue/MetroContainer.java b/appserver/webservices/metro-glue/src/main/java/org/glassfish/webservices/metroglue/MetroContainer.java index c73c2f2ff8c..b84194aa826 100644 --- a/appserver/webservices/metro-glue/src/main/java/org/glassfish/webservices/metroglue/MetroContainer.java +++ b/appserver/webservices/metro-glue/src/main/java/org/glassfish/webservices/metroglue/MetroContainer.java @@ -168,8 +168,8 @@ public void deployWsTxServices(String target) { File root = serverContext.getInstallRoot(); File app = null; try { - app = FileUtils.copyResource(root, "lib", "install", "applications", "metro", - WSTX_SERVICES_APP_NAME + ".war"); + File outputDir = new File(root, "lib/install/applications/metro"); + app = FileUtils.copyResourceToDirectory(WSTX_SERVICES_APP_NAME + ".war", outputDir); } catch (Exception e) { logger.log(Level.WARNING, LogUtils.WSTX_SERVICE_UNEXPECTED_EXCEPTION, e); } diff --git a/nucleus/common/common-util/src/main/java/com/sun/enterprise/util/io/FileUtils.java b/nucleus/common/common-util/src/main/java/com/sun/enterprise/util/io/FileUtils.java index 57b747676e1..44884523d60 100644 --- a/nucleus/common/common-util/src/main/java/com/sun/enterprise/util/io/FileUtils.java +++ b/nucleus/common/common-util/src/main/java/com/sun/enterprise/util/io/FileUtils.java @@ -19,8 +19,6 @@ import com.sun.enterprise.util.OS; -import java.io.BufferedInputStream; -import java.io.BufferedOutputStream; import java.io.BufferedReader; import java.io.File; import java.io.FileFilter; @@ -41,7 +39,6 @@ import java.nio.channels.ReadableByteChannel; import java.nio.channels.WritableByteChannel; import java.nio.file.Files; -import java.nio.file.Path; import java.nio.file.StandardCopyOption; import java.util.Collection; import java.util.Locale; @@ -641,29 +638,6 @@ private static int doWithRetry(RetriableWork work) { } - /** - * Copies a file. - * - * @param fin File to copy - * @param fout New file - * @throws IOException if an error while copying the content - */ - public static void copy(File fin, File fout) throws IOException { - if (safeIsDirectory(fin)) { - copyTree(fin, fout); - return; - } - if (!fin.exists()) { - throw new IllegalArgumentException("File source doesn't exist"); - } - if (!mkdirsMaybe(fout.getParentFile())) { - throw new RuntimeException("Can't create parent dir of output file: " + fout); - } - Files.copy(fin.toPath(), fout.toPath()); - LOG.log(Level.DEBUG, "Successfully copyied file {0} to {1}", fin, fout); - } - - /** * Copies the entire tree to a new location. * @@ -691,6 +665,66 @@ public static void copyTree(File din, File dout) throws IOException { } + public static File copyResourceToDirectory(String resourcePath, File outputDirectory) throws IOException { + int slashIndex = resourcePath.lastIndexOf('/'); + String fileName = slashIndex < 0 ? resourcePath : resourcePath.substring(slashIndex + 1); + File output = new File(outputDirectory, fileName); + if (output.exists()) { + return output; + } + return copyResource(resourcePath, output); + } + + + /** + * If the path dir/file does not exist, look for it in the classpath. + * If found in classpath, create dir/file. + *

+ * Existing file will not be overwritten. + * + * @param resourcePath - resource loadable by the thread context classloader. + * @param outputFile - if the file exists, it will be overwritten + * @return the File representing dir/file. If the resource does not exist, return null. + * @throws IOException + */ + public static File copyResource(String resourcePath, File outputFile) throws IOException { + LOG.log(Level.INFO, "copyResource(resourcePath={0}, outputFile={1})", resourcePath, outputFile); + try (InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream(resourcePath)) { + if (is == null) { + return null; + } + if (!mkdirsMaybe(outputFile.getParentFile())) { + throw new IOException("Can't create parent dir of output file: " + outputFile); + } + copy(is, outputFile); + return outputFile; + } + } + + + /** + * Copies a file. + * + * @param fin File to copy + * @param fout New file + * @throws IOException if an error while copying the content + */ + public static void copy(File fin, File fout) throws IOException { + if (safeIsDirectory(fin)) { + copyTree(fin, fout); + return; + } + if (!fin.exists()) { + throw new IllegalArgumentException("File source doesn't exist"); + } + if (!mkdirsMaybe(fout.getParentFile())) { + throw new RuntimeException("Can't create parent dir of output file: " + fout); + } + Files.copy(fin.toPath(), fout.toPath(), StandardCopyOption.REPLACE_EXISTING); + LOG.log(Level.DEBUG, "Successfully copyied file {0} to {1}", fin, fout); + } + + /** * Returns a String with uniform slashes such that all the * occurances of '\\' are replaced with '/'. @@ -792,7 +826,11 @@ public static void copy(InputStream in, File out, long byteCount) throws IOExcep * @throws IOException */ public static void copy(InputStream in, File out) throws IOException { - Files.copy(in, out.toPath(), StandardCopyOption.REPLACE_EXISTING); + if (out.getParentFile().mkdirs()) { + LOG.log(Level.INFO, "Created directory {0}", out.getCanonicalPath()); + } + long bytes = Files.copy(in, out.toPath(), StandardCopyOption.REPLACE_EXISTING); + LOG.log(Level.INFO, "Copyied {0} bytes to {1}", bytes, out); } @@ -886,36 +924,6 @@ public static String readSmallFile(final File file) throws IOException { } - /** - * If the path dir/file does not exist, look for it in the classpath. - * If found in classpath, create dir/file. - *

- * Existing file will not be overwritten. - * - * @param dir - directory where the path file should exist (including resource path) - * @param resourcePath - resource loadable by the thread context classloader. - * @return the File representing dir/file. If that does not exist, return null. - * @throws IOException - */ - public static File copyResource(File dir, String... resourcePath) throws IOException { - File f = new File(dir, String.join(File.separator, resourcePath)); - if (f.exists()) { - return f; - } - try (InputStream is = Thread.currentThread().getContextClassLoader() - .getResourceAsStream(String.join("/", resourcePath))) { - if (is == null) { - return null; - } - if (!mkdirsMaybe(f.getParentFile())) { - throw new IOException("Can't create parent dir of output file: " + f); - } - copy(is, f); - return f; - } - } - - /** * Write the String to a file. Then make the file readable and writable. * If the file already exists it will be truncated and the contents replaced diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/common/EmbeddedSecurityLifeCycle.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/common/EmbeddedSecurityLifeCycle.java index afbc9c0b898..254d5b38267 100644 --- a/nucleus/security/core/src/main/java/com/sun/enterprise/security/common/EmbeddedSecurityLifeCycle.java +++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/common/EmbeddedSecurityLifeCycle.java @@ -68,16 +68,17 @@ public void creation(Server server) { try { //Get the keyfile names from the security service List keyFileNames = embeddedSecurity.getKeyFileNames(securityService); + File cfgDir = new File(instanceRoot, "config"); for (String keyFileName : keyFileNames) { // Copy the keyfiles in instanceRoot/config. If file is already present, then exit (handled by getManagedFile) - FileUtils.copyResource(instanceRoot, "config", embeddedSecurity.parseFileName(keyFileName)); + FileUtils.copyResourceToDirectory(embeddedSecurity.parseFileName(keyFileName), cfgDir); } //Copy the other security files to instanceRoot/config //Assuming that these files are present as config/filename in the embedded jar file and are to be extracted that way/ - FileUtils.copyResource(instanceRoot,"config", "login.conf"); - FileUtils.copyResource(instanceRoot,"config", "server.policy"); - FileUtils.copyResource(instanceRoot,"config", "cacerts.jks"); - FileUtils.copyResource(instanceRoot,"config", "keystore.jks"); + FileUtils.copyResourceToDirectory("login.conf", cfgDir); + FileUtils.copyResourceToDirectory("server.policy", cfgDir); + FileUtils.copyResourceToDirectory("cacerts.jks", cfgDir); + FileUtils.copyResourceToDirectory("keystore.jks", cfgDir); String keystoreFile = null; String truststoreFile = null; try { From 5872a8e0cb8d2372a93ca0c3a749162de7ca1bf4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Mat=C4=9Bj=C4=8Dek?= Date: Sun, 8 Oct 2023 03:44:15 +0200 Subject: [PATCH 11/12] Reduced logging MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: David Matějček --- .../template/src/main/resources/config/logging.properties | 1 + .../main/java/com/sun/enterprise/util/io/FileUtils.java | 8 ++++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/nucleus/admin/template/src/main/resources/config/logging.properties b/nucleus/admin/template/src/main/resources/config/logging.properties index 7aa303e2c1a..d81b0881a2c 100644 --- a/nucleus/admin/template/src/main/resources/config/logging.properties +++ b/nucleus/admin/template/src/main/resources/config/logging.properties @@ -69,6 +69,7 @@ com.sun.enterprise.naming.level=INFO com.sun.enterprise.resource.level=INFO com.sun.enterprise.security.level=INFO com.sun.enterprise.universal.level=INFO +com.sun.enterprise.util.io.level=INFO com.sun.webui.level=INFO jakarta.level=INFO diff --git a/nucleus/common/common-util/src/main/java/com/sun/enterprise/util/io/FileUtils.java b/nucleus/common/common-util/src/main/java/com/sun/enterprise/util/io/FileUtils.java index 44884523d60..73b11aea573 100644 --- a/nucleus/common/common-util/src/main/java/com/sun/enterprise/util/io/FileUtils.java +++ b/nucleus/common/common-util/src/main/java/com/sun/enterprise/util/io/FileUtils.java @@ -688,7 +688,7 @@ public static File copyResourceToDirectory(String resourcePath, File outputDirec * @throws IOException */ public static File copyResource(String resourcePath, File outputFile) throws IOException { - LOG.log(Level.INFO, "copyResource(resourcePath={0}, outputFile={1})", resourcePath, outputFile); + LOG.log(DEBUG, "copyResource(resourcePath={0}, outputFile={1})", resourcePath, outputFile); try (InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream(resourcePath)) { if (is == null) { return null; @@ -721,7 +721,7 @@ public static void copy(File fin, File fout) throws IOException { throw new RuntimeException("Can't create parent dir of output file: " + fout); } Files.copy(fin.toPath(), fout.toPath(), StandardCopyOption.REPLACE_EXISTING); - LOG.log(Level.DEBUG, "Successfully copyied file {0} to {1}", fin, fout); + LOG.log(DEBUG, "Successfully copyied file {0} to {1}", fin, fout); } @@ -827,10 +827,10 @@ public static void copy(InputStream in, File out, long byteCount) throws IOExcep */ public static void copy(InputStream in, File out) throws IOException { if (out.getParentFile().mkdirs()) { - LOG.log(Level.INFO, "Created directory {0}", out.getCanonicalPath()); + LOG.log(DEBUG, "Created directory {0}", out.getCanonicalPath()); } long bytes = Files.copy(in, out.toPath(), StandardCopyOption.REPLACE_EXISTING); - LOG.log(Level.INFO, "Copyied {0} bytes to {1}", bytes, out); + LOG.log(DEBUG, "Copyied {0} bytes to {1}", bytes, out); } From bd6374aeefccf082f6ec12254c02345b5fb849d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Mat=C4=9Bj=C4=8Dek?= Date: Wed, 21 Feb 2024 09:48:35 +0100 Subject: [PATCH 12/12] Added few finals and replaced redundant new File in SetupSshKey MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: David Matějček --- .../sun/enterprise/admin/cli/cluster/SetupSshKey.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/nucleus/cluster/cli/src/main/java/com/sun/enterprise/admin/cli/cluster/SetupSshKey.java b/nucleus/cluster/cli/src/main/java/com/sun/enterprise/admin/cli/cluster/SetupSshKey.java index c130f8552f8..c19efae41bb 100644 --- a/nucleus/cluster/cli/src/main/java/com/sun/enterprise/admin/cli/cluster/SetupSshKey.java +++ b/nucleus/cluster/cli/src/main/java/com/sun/enterprise/admin/cli/cluster/SetupSshKey.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Contributors to the Eclipse Foundation + * Copyright (c) 2022, 2024 Contributors to the Eclipse Foundation * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the @@ -66,7 +66,7 @@ protected void validate() throws CommandException { if (sshkeyfile == null) { // if user hasn't specified a key file and there is no key file at default // location, then generate one - File existingKey = SSHUtil.getExistingKeyFile(); + final File existingKey = SSHUtil.getExistingKeyFile(); if (existingKey == null) { sshkeyfile = SSHUtil.getDefaultKeyFile().getAbsolutePath(); if (promptForKeyGeneration()) { @@ -81,9 +81,9 @@ protected void validate() throws CommandException { } } } else { - File keyFile = new File(sshkeyfile); + final File keyFile = new File(sshkeyfile); promptPass = SSHUtil.validateKeyFile(keyFile); - if (SSHUtil.isEncryptedKey(new File(sshkeyfile))) { + if (SSHUtil.isEncryptedKey(keyFile)) { sshkeypassphrase = getSSHPassphrase(false); } } @@ -101,7 +101,7 @@ protected int executeCommand() throws CommandException { String previousPassword = null; boolean status = false; for (String node : hosts) { - File keyFile = sshkeyfile == null ? null : new File(sshkeyfile); + final File keyFile = sshkeyfile == null ? null : new File(sshkeyfile); sshL.init(getRemoteUser(), node, getRemotePort(), sshpassword, keyFile, sshkeypassphrase, logger); if (generatekey || promptPass) { //prompt for password iff required