[ https://issues.apache.org/jira/browse/KNOX-3051?focusedWorklogId=946321&page=com.atlassian.jira.plugin.system.issuetabpanels:worklog-tabpanel#worklog-946321 ]
ASF GitHub Bot logged work on KNOX-3051: ---------------------------------------- Author: ASF GitHub Bot Created on: 02/Dec/24 10:09 Start Date: 02/Dec/24 10:09 Worklog Time Spent: 10m Work Description: smolnar82 commented on code in PR #971: URL: https://github.com/apache/knox/pull/971#discussion_r1865570612 ########## gateway-util-launcher/src/main/java/org/apache/knox/gateway/launcher/Extender.java: ########## @@ -0,0 +1,77 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.knox.gateway.launcher; + +import java.io.File; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Arrays; +import java.util.Properties; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class Extender { + + private static final String CLASSPATH_EXTENSION_PROPERTY = "gateway.server.classpath.extension"; + private static final String CLASSPATH_PROPERTY_PATTERN = "<property>\\s*<name>" + CLASSPATH_EXTENSION_PROPERTY + "</name>\\s*<value>(.*?)</value>\\s*</property>"; + private static final String CONFIG_FILE = "gateway-site.xml"; + private static final String CONFIG_PATH = "../conf/" + CONFIG_FILE; + private static final String CLASS_PATH_PROPERTY = "class.path"; + private static final String MAIN_CLASS_PROPERTY = "main.class"; + private static final String GATEWAY_SERVER_MAIN_CLASS = "org.apache.knox.gateway.GatewayServer"; + private static final String[] CLASS_PATH_DELIMITERS = new String[]{",", ";"}; + + private final File base; + private final Properties properties; + + public Extender(File base, Properties properties) { + this.base = base; + this.properties = properties; + } + + public void extendClassPathProperty() throws IOException { + Path configFilePath = Paths.get(base.getPath(), CONFIG_PATH); + if (GATEWAY_SERVER_MAIN_CLASS.equals(properties.getProperty(MAIN_CLASS_PROPERTY)) && Files.isReadable(configFilePath)) { + String configContent = new String(Files.readAllBytes(configFilePath), StandardCharsets.UTF_8); + extractExtensionPathIntoProperty(configContent); + } + } + + protected void extractExtensionPathIntoProperty(String configContent) { + Pattern pattern = Pattern.compile(CLASSPATH_PROPERTY_PATTERN, Pattern.DOTALL); + Matcher matcher = pattern.matcher(configContent); Review Comment: nit: they can be `final`. ########## gateway-util-launcher/src/test/java/org/apache/knox/gateway/launcher/ExtenderTest.java: ########## @@ -0,0 +1,195 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.knox.gateway.launcher; + + +import org.junit.Test; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Properties; + +import static org.junit.Assert.assertEquals; + +public class ExtenderTest { + + private Path tempDir; + private Path confDir; + private Path configFilePath; + + @Test + public void extendClassPathPropertyTest() throws IOException { + this.setupDirs(); + Properties properties = new Properties(); + properties.setProperty("class.path", "classpath"); + properties.setProperty("main.class", "org.apache.knox.gateway.GatewayServer"); + Extender extender = new Extender(confDir.toFile(), properties); + + String configContent = this.getConfigContent("/new/classp/*"); + Files.write(configFilePath, configContent.getBytes(StandardCharsets.UTF_8)); + extender.extendClassPathProperty(); + + assertEquals("/new/classp/*;classpath", properties.getProperty("class.path")); + this.cleanUpDirs(); + } + + @Test + public void extendClassPathPropertyDifferentMainClassTest() throws IOException { + this.setupDirs(); + Properties properties = new Properties(); + properties.setProperty("class.path", "classpath"); + properties.setProperty("main.class", "org.apache.knox.gateway.KnoxCLI"); + Extender extender = new Extender(confDir.toFile(), properties); + + String configContent = this.getConfigContent("/new/classp/*"); + Files.write(configFilePath, configContent.getBytes(StandardCharsets.UTF_8)); + extender.extendClassPathProperty(); + + assertEquals("classpath", properties.getProperty("class.path")); + this.cleanUpDirs(); + } + + @Test + public void extractExtensionPathIntoPropertyNoDelimTest() { + Properties properties = new Properties(); + properties.setProperty("class.path", "classpath"); + Extender extender = new Extender(null, properties); + + String configContent = this.getConfigContent("/new/classp/*"); + extender.extractExtensionPathIntoProperty(configContent); + + assertEquals("/new/classp/*;classpath", properties.getProperty("class.path")); + } + + @Test + public void extractExtensionPathIntoPropertyXMLFormatTest() { + Properties properties = new Properties(); + properties.setProperty("class.path", "classpath"); + Extender extender = new Extender(null, properties); + + String configContent = this.getConfigContent("/new/classp/*;"); + extender.extractExtensionPathIntoProperty(configContent); + + assertEquals("/new/classp/*;classpath", properties.getProperty("class.path")); + } + + @Test + public void extractExtensionPathIntoPropertyWhitespaceTest() { + Properties properties = new Properties(); + properties.setProperty("class.path", "classpath"); + Extender extender = new Extender(null, properties); + + String configContent = this.getConfigContent(" /new/classp/*; "); + extender.extractExtensionPathIntoProperty(configContent); + + assertEquals("/new/classp/*;classpath", properties.getProperty("class.path")); + } + + @Test + public void extractExtensionPathIntoPropertyMultipleTest() { + Properties properties = new Properties(); + properties.setProperty("class.path", "classpath"); + Extender extender = new Extender(null, properties); + + String configContent = this.getConfigContent("/new/classp/*,../classp"); + extender.extractExtensionPathIntoProperty(configContent); + + assertEquals("/new/classp/*,../classp;classpath", properties.getProperty("class.path")); + } + + @Test + public void extractExtensionPathIntoPropertyEmptyTest() { + Properties properties = new Properties(); + properties.setProperty("class.path", "classpath"); + Extender extender = new Extender(null, properties); + + String configContent = this.getConfigContent(""); + extender.extractExtensionPathIntoProperty(configContent); + + assertEquals("classpath", properties.getProperty("class.path")); + } + + @Test + public void extractExtensionPathIntoPropertyEmptyWhitespaceTest() { + Properties properties = new Properties(); + properties.setProperty("class.path", "classpath"); + Extender extender = new Extender(null, properties); + + String configContent = this.getConfigContent(" "); + extender.extractExtensionPathIntoProperty(configContent); + + assertEquals("classpath", properties.getProperty("class.path")); + } + + @Test + public void extractExtensionPathIntoPropertyNoConfigTest() { + Properties properties = new Properties(); + properties.setProperty("class.path", "classpath"); + Extender extender = new Extender(null, properties); + + String configContent = + "<configuration>\n" + + " <property>\n" + + " <name>gateway.webshell.read.buffer.size</name>\n" + + " <value>1024</value>\n" + + " <description>Web Shell buffer size for reading</description>\n" + + " </property>\n" + + "\n" + + " <! Issue Time Tracking ------------------- Worklog Id: (was: 946321) Time Spent: 20m (was: 10m) > Add a classpath location for patches > ------------------------------------ > > Key: KNOX-3051 > URL: https://issues.apache.org/jira/browse/KNOX-3051 > Project: Apache Knox > Issue Type: Improvement > Components: Server > Affects Versions: 2.0.0 > Reporter: Philip Zampino > Priority: Minor > Time Spent: 20m > Remaining Estimate: 0h > > It would be convenient to have the ability to easily pre-pend classes to the > Knox classpath for quickly applying/testing patches. > If this could be configurable, that would be ideal, though I'm not sure it's > possible. > If hard-coded, we should consider whether or not this location should be > within the Knox installation directory or external to it. There are pros and > cons to both, especially when considering upgrades in managed environments. -- This message was sent by Atlassian Jira (v8.20.10#820010)