From 072bc17cb16400675e21335fe08fa72e7ee13c9f Mon Sep 17 00:00:00 2001 From: Thomas Florio Date: Mon, 17 Jul 2023 11:05:19 +0200 Subject: [PATCH 1/3] Implemented find() as default interface method --- .../code/src/com/redhat/rhn/common/finder/FileFinder.java | 8 +------- java/code/src/com/redhat/rhn/common/finder/Finder.java | 4 +++- java/code/src/com/redhat/rhn/common/finder/JarFinder.java | 7 ------- 3 files changed, 4 insertions(+), 15 deletions(-) diff --git a/java/code/src/com/redhat/rhn/common/finder/FileFinder.java b/java/code/src/com/redhat/rhn/common/finder/FileFinder.java index 0d28b9b20507..76eb7c275fe9 100644 --- a/java/code/src/com/redhat/rhn/common/finder/FileFinder.java +++ b/java/code/src/com/redhat/rhn/common/finder/FileFinder.java @@ -20,6 +20,7 @@ import java.io.File; import java.util.Arrays; +import java.util.Collections; import java.util.LinkedList; import java.util.List; @@ -41,13 +42,6 @@ class FileFinder implements Finder { } } - /** {@inheritDoc} */ - @Override - public List find(String endStr) { - return findExcluding(null, endStr); - } - - /** {@inheritDoc} */ @Override public List findExcluding(String[] excludes, String endStr) { List results = new LinkedList<>(); diff --git a/java/code/src/com/redhat/rhn/common/finder/Finder.java b/java/code/src/com/redhat/rhn/common/finder/Finder.java index 6d81a605ce3d..53cbd843b5d8 100644 --- a/java/code/src/com/redhat/rhn/common/finder/Finder.java +++ b/java/code/src/com/redhat/rhn/common/finder/Finder.java @@ -31,7 +31,9 @@ public interface Finder { * @return a list of all classes within the package that end with the * specified string */ - List find(String endStr); + default List find(String endStr) { + return findExcluding(null, endStr); + } /** * Find all files within a package that end with the specified string diff --git a/java/code/src/com/redhat/rhn/common/finder/JarFinder.java b/java/code/src/com/redhat/rhn/common/finder/JarFinder.java index 0cbc6b845e1e..595ca2f60637 100644 --- a/java/code/src/com/redhat/rhn/common/finder/JarFinder.java +++ b/java/code/src/com/redhat/rhn/common/finder/JarFinder.java @@ -41,13 +41,6 @@ class JarFinder implements Finder { url = packageUrl; } - /** {@inheritDoc} */ - @Override - public List find(String endStr) { - return findExcluding(null, endStr); - } - - /** {@inheritDoc} */ @Override public List findExcluding(String[] excludes, String endStr) { try { From 121a1b8627b90795bb0f8041dca59aca3296bc6d Mon Sep 17 00:00:00 2001 From: Thomas Florio Date: Mon, 17 Jul 2023 11:06:53 +0200 Subject: [PATCH 2/3] Added CompositeFinder to merge multiple finders results --- .../rhn/common/finder/CompositeFinder.java | 40 +++++++++++++++++++ .../redhat/rhn/common/finder/FileFinder.java | 2 +- .../common/finder/test/FileFinderTest.java | 4 +- 3 files changed, 43 insertions(+), 3 deletions(-) create mode 100644 java/code/src/com/redhat/rhn/common/finder/CompositeFinder.java diff --git a/java/code/src/com/redhat/rhn/common/finder/CompositeFinder.java b/java/code/src/com/redhat/rhn/common/finder/CompositeFinder.java new file mode 100644 index 000000000000..6acd8c5e570d --- /dev/null +++ b/java/code/src/com/redhat/rhn/common/finder/CompositeFinder.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2023 SUSE LLC + * + * This software is licensed to you under the GNU General Public License, + * version 2 (GPLv2). There is NO WARRANTY for this software, express or + * implied, including the implied warranties of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. You should have received a copy of GPLv2 + * along with this software; if not, see + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. + * + * Red Hat trademarks are not licensed under GPLv2. No permission is + * granted to use or replicate Red Hat trademarks that are incorporated + * in this software or its documentation. + */ + +package com.redhat.rhn.common.finder; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.stream.Collectors; + +/** + * A Finder implementation that uses multiple finders to search + */ +class CompositeFinder implements Finder { + + private final List finderList; + + CompositeFinder(Collection finders) { + this.finderList = new ArrayList<>(finders); + } + + @Override + public List findExcluding(String[] excluding, String endStr) { + return this.finderList.stream() + .flatMap(finder -> finder.findExcluding(excluding, endStr).stream()) + .collect(Collectors.toList()); + } +} diff --git a/java/code/src/com/redhat/rhn/common/finder/FileFinder.java b/java/code/src/com/redhat/rhn/common/finder/FileFinder.java index 76eb7c275fe9..b6550e1cbf19 100644 --- a/java/code/src/com/redhat/rhn/common/finder/FileFinder.java +++ b/java/code/src/com/redhat/rhn/common/finder/FileFinder.java @@ -49,7 +49,7 @@ public List findExcluding(String[] excludes, String endStr) { if (!startDir.exists()) { // Shouldn't ever happen, because the FinderFactory should only // return a FileFinder. - return null; + return Collections.emptyList(); } String[] fileList = startDir.list(); diff --git a/java/code/src/com/redhat/rhn/common/finder/test/FileFinderTest.java b/java/code/src/com/redhat/rhn/common/finder/test/FileFinderTest.java index 396c79332a85..05c446c618de 100644 --- a/java/code/src/com/redhat/rhn/common/finder/test/FileFinderTest.java +++ b/java/code/src/com/redhat/rhn/common/finder/test/FileFinderTest.java @@ -51,7 +51,7 @@ public void testFindFilesSubDir() { assertNotNull(f); List result = f.find(".class"); - assertEquals(6, result.size()); + assertEquals(7, result.size()); } @Test @@ -60,7 +60,7 @@ public void testFindExcluding() { assertNotNull(f); String[] sarr = {"Test"}; List result = f.findExcluding(sarr, "class"); - assertEquals(4, result.size()); + assertEquals(5, result.size()); } } From 0c67df14d5c86d3abd0801697c3446ed1cd17759 Mon Sep 17 00:00:00 2001 From: Thomas Florio Date: Mon, 17 Jul 2023 11:18:53 +0200 Subject: [PATCH 3/3] Added multiple URLs support in FinderFactory --- .../rhn/common/finder/FinderFactory.java | 59 +++++++++++++++---- 1 file changed, 48 insertions(+), 11 deletions(-) diff --git a/java/code/src/com/redhat/rhn/common/finder/FinderFactory.java b/java/code/src/com/redhat/rhn/common/finder/FinderFactory.java index 19ee49fb1d43..1875f5cc13a3 100644 --- a/java/code/src/com/redhat/rhn/common/finder/FinderFactory.java +++ b/java/code/src/com/redhat/rhn/common/finder/FinderFactory.java @@ -15,8 +15,17 @@ package com.redhat.rhn.common.finder; +import org.apache.commons.lang3.StringUtils; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + import java.io.File; +import java.io.IOException; import java.net.URL; +import java.util.Collections; +import java.util.Enumeration; +import java.util.List; +import java.util.stream.Collectors; /** * A factory that returns the correct type of finder. @@ -24,6 +33,8 @@ */ public class FinderFactory { + private static final Logger LOGGER = LogManager.getLogger(FinderFactory.class); + private FinderFactory() { } @@ -33,27 +44,53 @@ private FinderFactory() { * @return Finder to use for given package name. */ public static Finder getFinder(String packageName) { - // Start by translating into an absolute path. - String name = packageName; - if (!packageName.startsWith("/")) { - name = "/" + name; + // Extract all the possible URLs for a package + List possibleUrls = getAllUrlsForPackage(packageName); + if (possibleUrls.isEmpty()) { + throw new IllegalArgumentException("Not a well-formed jar file"); + } + + if (possibleUrls.size() == 1) { + return getFinderForPackage(packageName, possibleUrls.get(0)); } - name = name.replace('.', '/'); - URL packageUrl = FinderFactory.class.getResource(name); + return possibleUrls.stream() + .map(packageUrl -> getFinderForPackage(packageName, packageUrl)) + .collect(Collectors.collectingAndThen(Collectors.toList(), CompositeFinder::new)); + } + + private static List getAllUrlsForPackage(String packageName) { + try { + ClassLoader classLoader = FinderFactory.class.getClassLoader(); + Enumeration systemResources = classLoader.getResources(packageName.replace('.', '/')); + if (systemResources == null || !systemResources.hasMoreElements()) { + LOGGER.warn("No valid URLs found for package {}", packageName); + return Collections.emptyList(); + } - // This only happens if the .jar file isn't well-formed, so we - // shouldn't have this problem, ever. - if (packageUrl == null) { - throw new IllegalArgumentException("Not a well formed jar file"); + return Collections.list(systemResources); } + catch (SecurityException ex) { + throw new IllegalStateException("Unable to access the class loader for searching " + packageName, ex); + } + catch (IOException ex) { + LOGGER.warn("Unable to find URLs for package {}", packageName, ex); + return Collections.emptyList(); + } + } + private static Finder getFinderForPackage(String packageName, URL packageUrl) { File directory = new File(packageUrl.getFile()); if (!directory.isFile() && !directory.isDirectory()) { // This is a jar file that we are dealing with. return new JarFinder(packageUrl); } - return new FileFinder(directory, name); + + return new FileFinder(directory, getAbsolutePath(packageName)); + } + + private static String getAbsolutePath(String packageName) { + return StringUtils.prependIfMissing(packageName, "/").replace('.', '/'); } }