diff --git a/.gitignore b/.gitignore index 3faa08ea..5a45490c 100644 --- a/.gitignore +++ b/.gitignore @@ -5,5 +5,6 @@ nbproject/build-impl.xml nbproject/genfiles.properties nbproject/private/* .gradle +.m2-cache build-ext.properties \ No newline at end of file diff --git a/build.properties b/build.properties index d203f9fa..dc989a77 100644 --- a/build.properties +++ b/build.properties @@ -14,17 +14,8 @@ project.dir=portal ignored.dirs=.git,.gradle,build,node_modules,portal-compat,sample,support-websphere,tmp,tools,.releng -display.gradle.process.output=false - jpda.settings=-agentlib:jdwp=transport=dt_socket,address=8000,server=y,suspend=y group.stop.words=third-party,modules -include.generated.jsp.servlet=false - -#Please provide comma separated path of excluded module relative to liferay-portal/modules -#Example: gradle.build.exclude.dirs=apps/collaboration/blogs,apps/foundation/portal-search -gradle.build.exclude.dirs=sdk/project-templates -gradle.build.exclude.dirs= - -gradle.opts=-Xmx3g \ No newline at end of file +include.generated.jsp.servlet=false \ No newline at end of file diff --git a/dependency.gradle b/dependency.gradle deleted file mode 100644 index 93dd8fef..00000000 --- a/dependency.gradle +++ /dev/null @@ -1,78 +0,0 @@ -allprojects { - repositories { - maven { - url "https://repository.liferay.com/nexus/content/groups/public" - } - mavenCentral() - mavenLocal() - } - - configurations.whenObjectAdded { - Configuration configuration -> - - if (configuration.name == "compileOnly") { - configuration.dependencies.all { - transitive = false - } - } - } - - task printDependencies { - doLast { - StringBuilder sb = new StringBuilder(); - - ["compile", "compileOnly", "compileInclude", "testIntegrationCompile", "testIntegrationRuntime"].each { - Configuration configuration = configurations.findByName it - - if (configuration) { - if (configuration.name == "compile") { - sb.append("compile=") - } - else if (configuration.name == "compileOnly") { - sb.append("compileOnly=") - } - else if (configuration.name == "compileInclude") { - sb.append("compileInclude=") - } - else { - sb.append("compileTest=") - } - - configuration.files.each { - sb.append(it) - sb.append(':') - } - - sb.append('\n') - - def componentIds = configuration.incoming.resolutionResult.allDependencies.collect { - it.selected.id - } - - def result = dependencies.createArtifactResolutionQuery() - .forComponents(componentIds) - .withArtifacts(JvmLibrary, SourcesArtifact) - .execute() - - sb.append(configuration.name) - sb.append("Sources=") - - for (component in result.resolvedComponents) { - component.getArtifacts(SourcesArtifact).each { - sb.append("${it.file}") - sb.append(':') - } - } - - sb.append('\n') - } - } - - if (sb.length() != 0) { - def file = new File(dependencyDirectory + File.separator + project.getName()) - - file.text = sb - } - } - } -} diff --git a/portal-module-dependency.properties b/portal-module-dependency.properties index 2b397e69..e0e6d2fa 100644 --- a/portal-module-dependency.properties +++ b/portal-module-dependency.properties @@ -7,11 +7,11 @@ #Add modules as dependency to other modules petra.modules=petra-concurrent,petra-executor,petra-function,petra-io,petra-lang,petra-memory,petra-nio,petra-process,petra-reflect,petra-sql-dsl-api,petra-sql-dsl-spi,petra-string,osgi-service-tracker-collections -portal-impl=portal-kernel,util-bridges,util-java,util-taglib,petra-content,petra-log4j,petra-encryptor,petra-mail,petra-xml,petra-portlet-url-builder,petra-url-pattern-mapper +portal-impl=portal-kernel,util-bridges,util-java,util-taglib portal-kernel=osgi-service-tracker-collections -portal-test=portal-impl,portal-kernel,petra-log4j +portal-test=portal-impl,portal-kernel support-tomcat=portal-kernel util-bridges=portal-kernel util-java=portal-kernel,portal-test -util-taglib=portal-kernel,util-java,petra-encryptor +util-taglib=portal-kernel,util-java util-slf4j=portal-kernel \ No newline at end of file diff --git a/src/com/liferay/netbeansproject/ProjectBuilder.java b/src/com/liferay/netbeansproject/ProjectBuilder.java index 6f6c8d0f..3857b32b 100644 --- a/src/com/liferay/netbeansproject/ProjectBuilder.java +++ b/src/com/liferay/netbeansproject/ProjectBuilder.java @@ -18,6 +18,7 @@ import com.liferay.netbeansproject.container.Module; import com.liferay.netbeansproject.util.FileUtil; import com.liferay.netbeansproject.util.GradleUtil; +import com.liferay.netbeansproject.util.MavenUtil; import com.liferay.netbeansproject.util.ModuleUtil; import com.liferay.netbeansproject.util.PropertiesUtil; import com.liferay.netbeansproject.util.StringUtil; @@ -56,9 +57,6 @@ public static void main(String[] args) throws Exception { Path projectDirPath = Paths.get( PropertiesUtil.getRequiredProperty(buildProperties, "project.dir")); - boolean displayGradleProcessOutput = Boolean.valueOf( - buildProperties.getProperty("display.gradle.process.output")); - String ignoredDirs = PropertiesUtil.getRequiredProperty( buildProperties, "ignored.dirs"); @@ -66,16 +64,13 @@ public static void main(String[] args) throws Exception { PropertiesUtil.getRequiredProperty( buildProperties, "include.generated.jsp.servlet")); - String gradleBuildExcludeDirs = buildProperties.getProperty( - "gradle.build.exclude.dirs"); - - String gradleOpts = buildProperties.getProperty("gradle.opts"); - ProjectBuilder projectBuilder = new ProjectBuilder(); for (String portalDir : portalDirs) { Path portalDirPath = Paths.get(portalDir); + MavenUtil.buildCache(portalDirPath, buildProperties); + Properties appServerProperties = new Properties(); Path trunkPath = null; @@ -90,18 +85,15 @@ public static void main(String[] args) throws Exception { projectBuilder.scanPortal( projectDirPath.resolve(portalDirPath.getFileName()), - portalDirPath, displayGradleProcessOutput, ignoredDirs, - trunkPath, + portalDirPath, ignoredDirs, trunkPath, appServerProperties.getProperty("app.server.tomcat.version"), - includeJsps, gradleBuildExcludeDirs, gradleOpts); + includeJsps); } } public void scanPortal( - final Path projectPath, Path portalPath, - final boolean displayGradleProcessOutput, String ignoredDirs, - Path trunkPath, String tomcatVersion, boolean includeJsps, - String gradleBuildExcludeDirs, String gradleOpts) + final Path projectPath, Path portalPath, String ignoredDirs, + Path trunkPath, String tomcatVersion, boolean includeJsps) throws Exception { final Set ignoredDirSet = new HashSet<>( @@ -170,20 +162,13 @@ public FileVisitResult preVisitDirectory( FileUtil.delete(projectPath); - Map> jarDependenciesMap = - GradleUtil.getJarDependencies( - portalPath, portalPath.resolve("modules"), - moduleProjectPaths.keySet(), displayGradleProcessOutput, false, - gradleBuildExcludeDirs, gradleOpts); - Set portalLibJars = ModuleUtil.getPortalLibJars(portalPath); for (Path modulePath : modulePaths) { Module module = Module.createModule( projectPath.resolve("modules"), modulePath, moduleDependenciesMap.get(modulePath), - jarDependenciesMap.get( - String.valueOf(modulePath.getFileName())), + MavenUtil.getDependencies(modulePath.resolve("build.gradle")), portalModuleDependencyProperties, trunkPath, includeJsps, portalPath); diff --git a/src/com/liferay/netbeansproject/container/Coordinate.java b/src/com/liferay/netbeansproject/container/Coordinate.java new file mode 100644 index 00000000..1bc1ea7e --- /dev/null +++ b/src/com/liferay/netbeansproject/container/Coordinate.java @@ -0,0 +1,154 @@ +/** + * SPDX-FileCopyrightText: (c) 2023 Liferay, Inc. https://liferay.com + * SPDX-License-Identifier: LGPL-2.1-or-later OR LicenseRef-Liferay-DXP-EULA-2.0.0-2023-06 + */ + +package com.liferay.netbeansproject.container; + +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Objects; + +/** + * @author Shuyang Zhou + */ +public class Coordinate implements Comparable { + + public Coordinate(String line) { + String[] parts = line.split(":"); + + _groupId = parts[0]; + _artifactId = parts[1]; + _version = parts[2]; + _test = false; + + _filePath = _toFilePath(_groupId, _artifactId, _version); + } + + + public Coordinate( + String groupId, String artifactId, String version, boolean test) { + + _groupId = groupId; + _artifactId = artifactId; + _version = version; + _test = test; + + _filePath = _toFilePath(groupId, artifactId, version); + } + + public Dependency toDependency(Path basePath) { + Path sourcePath = basePath.resolve(_filePath.replace(".jar", "-sources.jar")); + + if (Files.notExists(sourcePath)) { + sourcePath = null; + } + else { + sourcePath = sourcePath.toAbsolutePath(); + } + + return new Dependency(basePath.resolve(_filePath).toAbsolutePath(), sourcePath, _test); + } + + private static String _toFilePath(String groupId, String artifactId, String version) { + StringBuilder sb = new StringBuilder(); + + sb.append(groupId.replace('.', '/')); + sb.append('/'); + sb.append(artifactId); + sb.append('/'); + sb.append(version); + sb.append('/'); + sb.append(artifactId); + sb.append('-'); + sb.append(version); + sb.append(".jar"); + + return sb.toString(); + } + public String getFilePath() { + return _filePath; + } + + public String getGroupId() { + return _groupId; + } + + public String getArtifactId() { + return _artifactId; + } + + public String getVersion() { + return _version; + } + + public boolean isTest() { + return _test; + } + + public void setTest(boolean test) { + _test = test; + } + + private final String _groupId; + private final String _artifactId; + private final String _version; + private boolean _test; + private final String _filePath; + + @Override + public int hashCode() { + int hash = 7; + hash = 67 * hash + Objects.hashCode(this._groupId); + hash = 67 * hash + Objects.hashCode(this._artifactId); + hash = 67 * hash + Objects.hashCode(this._version); + hash = 67 * hash + (this._test ? 1 : 0); + return hash; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + final Coordinate other = (Coordinate)obj; + if (!Objects.equals(this._groupId, other._groupId)) { + return false; + } + if (!Objects.equals(this._artifactId, other._artifactId)) { + return false; + } + return Objects.equals(this._version, other._version); + } + + + @Override + public int compareTo(Coordinate coordinate) { + int result = _groupId.compareTo(coordinate._groupId); + + if (result != 0) { + return result; + } + + result = _artifactId.compareTo(coordinate._artifactId); + + if (result != 0) { + return result; + } + + return _version.compareTo(coordinate._version); + } + + @Override + public String toString() { + return _groupId + ":" + _artifactId + ":" + _version; + } + +} \ No newline at end of file diff --git a/src/com/liferay/netbeansproject/util/GradleUtil.java b/src/com/liferay/netbeansproject/util/GradleUtil.java index 6b8e9981..5747b222 100644 --- a/src/com/liferay/netbeansproject/util/GradleUtil.java +++ b/src/com/liferay/netbeansproject/util/GradleUtil.java @@ -20,7 +20,6 @@ import java.io.IOException; import java.io.InputStreamReader; -import java.nio.file.DirectoryStream; import java.nio.file.FileVisitOption; import java.nio.file.FileVisitResult; import java.nio.file.Files; @@ -30,7 +29,6 @@ import java.nio.file.attribute.BasicFileAttributes; import java.util.ArrayList; -import java.util.Collections; import java.util.EnumSet; import java.util.HashMap; import java.util.HashSet; @@ -38,7 +36,6 @@ import java.util.Map; import java.util.Properties; import java.util.Set; -import java.util.TreeSet; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; @@ -52,128 +49,6 @@ */ public class GradleUtil { - public static Map> getJarDependencies( - Path portalDirPath, Path workDirPath, Set symbolicNameSet, - boolean displayGradleProcessOutput, boolean daemon, - String gradleBuildExcludeDirs, String gradleOpts) - throws Exception { - - _checkPortalSnapshotsVersions(portalDirPath); - - Path dependenciesDirPath = Files.createTempDirectory(null); - - FileUtil.delete(dependenciesDirPath); - - Files.createDirectories(dependenciesDirPath); - - List gradleTask = new ArrayList<>(); - - gradleTask.add(String.valueOf(portalDirPath.resolve("gradlew"))); - - if (daemon) { - gradleTask.add("--daemon"); - } - - String userDir = System.getProperty("user.dir"); - - gradleTask.add("--parallel"); - gradleTask.add("--init-script=" + userDir + "/dependency.gradle"); - gradleTask.add("-p"); - gradleTask.add(String.valueOf(portalDirPath.resolve("modules"))); - gradleTask.add(_getTaskName(portalDirPath, workDirPath)); - gradleTask.add( - "-PdependencyDirectory=".concat(dependenciesDirPath.toString())); - gradleTask.add("-Dbuild.exclude.dirs=" + gradleBuildExcludeDirs); - gradleTask.add("-g"); - - Path gradleCachePath = Paths.get(".gradle"); - - Files.deleteIfExists(gradleCachePath.resolve("gradle.properties")); - - FileUtil.copy(portalDirPath.resolve(".gradle"), gradleCachePath); - - gradleTask.add(String.valueOf(gradleCachePath)); - - ProcessBuilder processBuilder = new ProcessBuilder(gradleTask); - - Map env = processBuilder.environment(); - - env.put("GRADLE_OPTS", gradleOpts); - - Process process = processBuilder.start(); - - if (displayGradleProcessOutput) { - String line = null; - - try (BufferedReader br = new BufferedReader( - new InputStreamReader(process.getInputStream()))) { - - while ((line = br.readLine()) != null) { - System.out.println(line); - } - } - - try (BufferedReader br = new BufferedReader( - new InputStreamReader(process.getErrorStream()))) { - - while ((line = br.readLine()) != null) { - System.out.println(line); - } - } - } - - int exitCode = process.waitFor(); - - if (exitCode != 0) { - throw new IOException( - "Process " + processBuilder.command() + " failed with " + - exitCode); - } - - Map> dependenciesMap = new HashMap<>(); - - try (DirectoryStream directoryStream = Files.newDirectoryStream( - dependenciesDirPath)) { - - String portalToolsPath = String.valueOf( - portalDirPath.resolve("tools/sdk")); - - for (Path dependencyPath : directoryStream) { - Set jarDependencies = new TreeSet<>(); - - jarDependencies.addAll( - _getConfigurationDependencies( - dependencyPath, "compile", "compileSources", false, - portalToolsPath, symbolicNameSet)); - - jarDependencies.addAll( - _getConfigurationDependencies( - dependencyPath, "compileOnly", "compileOnlySources", - false, portalToolsPath, symbolicNameSet)); - - jarDependencies.addAll( - _getConfigurationDependencies( - dependencyPath, "compileInclude", - "compileIncludeSources", false, portalToolsPath, - symbolicNameSet)); - - jarDependencies.addAll( - _getConfigurationDependencies( - dependencyPath, "compileTest", - "testIntegrationRuntimeSources", true, portalToolsPath, - symbolicNameSet)); - - dependenciesMap.put( - String.valueOf(dependencyPath.getFileName()), - jarDependencies); - } - } - - FileUtil.delete(dependenciesDirPath); - - return dependenciesMap; - } - public static Set getModuleDependencies( Path modulePath, Map moduleProjectPaths) throws IOException { diff --git a/src/com/liferay/netbeansproject/util/MavenUtil.java b/src/com/liferay/netbeansproject/util/MavenUtil.java new file mode 100644 index 00000000..8e3949a4 --- /dev/null +++ b/src/com/liferay/netbeansproject/util/MavenUtil.java @@ -0,0 +1,350 @@ +/** + * SPDX-FileCopyrightText: (c) 2023 Liferay, Inc. https://liferay.com + * SPDX-License-Identifier: LGPL-2.1-or-later OR LicenseRef-Liferay-DXP-EULA-2.0.0-2023-06 + */ + +package com.liferay.netbeansproject.util; + +import com.liferay.netbeansproject.container.Coordinate; +import com.liferay.netbeansproject.container.Dependency; +import java.io.IOException; +import java.io.InputStream; +import java.net.HttpURLConnection; +import java.net.URL; +import java.nio.file.FileVisitOption; +import java.nio.file.FileVisitResult; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.SimpleFileVisitor; +import java.nio.file.attribute.BasicFileAttributes; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.EnumSet; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.Set; +import java.util.TreeMap; +import java.util.TreeSet; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * @author Shuyang Zhou + */ +public class MavenUtil { + + public static Set getDependencies(Path buildGradlePath) { + Set dependencies = new HashSet<>(); + + List coordinates = _mavenCoordinates.get(buildGradlePath); + + if (coordinates != null) { + for (Coordinate coordinate : coordinates) { + dependencies.add(coordinate.toDependency(_cachePath)); + } + } + + for (Coordinate coordinate : _coordinateTestWhitelist) { + dependencies.add(coordinate.toDependency(_cachePath)); + } + + return dependencies; + } + + private static final Path _cachePath = Paths.get(".m2-cache"); + + public static boolean resolve(Coordinate coordinate) + throws IOException { + + String filePath = coordinate.getFilePath(); + + Path binaryPath = _cachePath.resolve(filePath); + + if (Files.exists(binaryPath)) { + return false; + } + + String location = _toLocation(filePath); + + try { + _downloadFile(filePath, location); + + _downloadSourcesFile(filePath, location); + } + catch (IOException ioException) { + _logger.log(Level.SEVERE, "Unable to resolve " + coordinate + " from " + location); + } + + return true; + } + + private static String _toLocation(String filePath) throws IOException { + URL url = new URL(_SEARCH_URL.concat(filePath)); + + for (int i = 0; i < 10; i++) { + HttpURLConnection httpURLConnection = + (HttpURLConnection)url.openConnection(); + + httpURLConnection.setInstanceFollowRedirects(false); + + int code = httpURLConnection.getResponseCode(); + + if (code == HttpURLConnection.HTTP_MOVED_TEMP) { + return httpURLConnection.getHeaderField("Location"); + } + + _logger.log( + Level.WARNING, "Retrying " + i + " for " + url + + " due to response code " + code); + } + + throw new IllegalStateException("Unable to get location for " + url); + } + + private static Path _downloadSourcesFile( + String filePath, String urlString) { + + String sourceURLString = _toSources(urlString); + + try { + return _downloadFile(_toSources(filePath), sourceURLString); + } + catch (IOException ioException) { + _logger.log( + Level.WARNING, "Unable to get source from " + sourceURLString); + + return null; + } + } + private static Path _downloadFile(String filePath, String urlString) + throws IOException { + + Path binaryPath = _cachePath.resolve(filePath); + + if (Files.exists(binaryPath)) { + return binaryPath; + } + + URL url = new URL(urlString); + + try (InputStream inputStream = url.openStream()) { + Files.createDirectories(binaryPath.getParent()); + + Files.copy(inputStream, binaryPath); + } + + return binaryPath; + } + + private static String _toSources(String value) { + return value.replace(".jar", "-sources.jar"); + } + + private static final Map> _mavenCoordinates = + new TreeMap<>(); + + public static void buildCache(Path portalPath, Properties buildProperties) + throws IOException { + + for (String line : StringUtil.split( + PropertiesUtil.getRequiredProperty( + buildProperties, "coordinate.blacklist"), ',')) { + + _coordinateBlacklist.add(new Coordinate(line.trim())); + } + + for (String line : StringUtil.split( + PropertiesUtil.getRequiredProperty( + buildProperties, "coordinate.test.whitelist"), ',')) { + + Coordinate coordinate = new Coordinate(line.trim()); + + coordinate.setTest(true); + + _coordinateTestWhitelist.add(coordinate); + } + + String ignoredDirs = PropertiesUtil.getRequiredProperty( + buildProperties, "ignored.dirs"); + + Set ignoredDirSet = new HashSet<>( + Arrays.asList(StringUtil.split(ignoredDirs, ','))); + + long startTime = System.currentTimeMillis(); + + Files.walkFileTree( + portalPath, EnumSet.allOf(FileVisitOption.class), Integer.MAX_VALUE, + new SimpleFileVisitor() { + + @Override + public FileVisitResult preVisitDirectory( + Path path, BasicFileAttributes basicFileAttributes) + throws IOException { + + if (ignoredDirSet.contains( + String.valueOf(path.getFileName()))) { + + return FileVisitResult.SKIP_SUBTREE; + } + + return FileVisitResult.CONTINUE; + } + + @Override + public FileVisitResult visitFile( + Path filePath, BasicFileAttributes basicFileAttributes) + throws IOException { + + String fileName = String.valueOf(filePath.getFileName()); + + if (fileName.equals("build.gradle")) { + _mavenCoordinates.put( + filePath, _parseCoordinates(filePath)); + } + + return FileVisitResult.CONTINUE; + } + + } + ); + + System.out.println( + "Scanned " + _mavenCoordinates.size() + " build.gradle in " + + (System.currentTimeMillis() - startTime) + "ms"); + + Set mergedCoordinates = new TreeSet<>(); + + for (List coordinates : _mavenCoordinates.values()) { + mergedCoordinates.addAll(coordinates); + } + + mergedCoordinates.removeAll(_coordinateBlacklist); + + mergedCoordinates.addAll(_coordinateTestWhitelist); + + System.out.println( + "Found " + mergedCoordinates.size() + " unique coordinates"); + + startTime = System.currentTimeMillis(); + + int resolved = 0; + + for (Coordinate coordinate : mergedCoordinates) { + if (resolve(coordinate)) { + resolved++; + } + } + + System.out.println("Skipped " + (mergedCoordinates.size() - resolved) + " coordinates, resolved " + resolved + " coordinates"); + } + + private static List _parseCoordinates(Path buildGradlePath) + throws IOException { + + List coordinates = new ArrayList<>(); + + for (String line : Files.readAllLines(buildGradlePath)) { + line = line.trim(); + + if (line.startsWith("api") || line.startsWith("parentThemes") || line.startsWith("match(")) { + continue; + } + + boolean test = line.startsWith("test"); + + int groupStartIndex = line.indexOf("group: \""); + + if (groupStartIndex == -1) { + continue; + } + + groupStartIndex += "group: \"".length(); + + int groupEndIndex = line.indexOf('"', groupStartIndex); + + if (groupEndIndex == -1) { + continue; + } + + String group = line.substring(groupStartIndex, groupEndIndex); + + int nameStartIndex = line.indexOf("name: \""); + + if (nameStartIndex == -1) { + continue; + } + + nameStartIndex += "name: \"".length(); + + int nameEndIndex = line.indexOf('"', nameStartIndex); + + if (nameEndIndex == -1) { + continue; + } + + String name = line.substring(nameStartIndex, nameEndIndex); + + int versionStartIndex = line.indexOf("version: \""); + + if (versionStartIndex == -1) { + continue; + } + + versionStartIndex += "version: \"".length(); + + int versionEndIndex = line.indexOf('"', versionStartIndex); + + if (versionEndIndex == -1) { + continue; + } + + String version = line.substring(versionStartIndex, versionEndIndex); + + // TODO Make sure these are added as a project dependency + + if (group.startsWith("com.liferay") && (version.equals("latest.release") || version.equals("default"))) { + continue; + } + + if (version.contains("@")) { + continue; + } + + if (version.endsWith("-LIFERAY-CACHED")) { + continue; + } + + Coordinate coordinate = new Coordinate(group, name, version, test); + + if (!_coordinateBlacklist.contains(coordinate)) { + coordinates.add(coordinate); + } + } + + Collections.sort(coordinates); + + return coordinates; + } + + public static void main(String[] args) throws IOException { + Properties buildProperties = PropertiesUtil.loadProperties( + Paths.get("build.properties")); + + buildCache(Paths.get("/home/trunks/git/liferay-portal"), buildProperties); + } + + private static final Set _coordinateBlacklist = new HashSet<>(); + + private static final Set _coordinateTestWhitelist = new HashSet<>(); + + private static final String _SEARCH_URL = + "https://search.maven.org/remotecontent?filepath="; + + private static final Logger _logger = Logger.getLogger( + MavenUtil.class.getName()); + +} \ No newline at end of file