diff --git a/modules/core/src/main/java/org/apache/ignite/internal/IgniteProperties.java b/modules/core/src/main/java/org/apache/ignite/internal/IgniteProperties.java index 75a49ccaaed0c..cc5c2c869f954 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/IgniteProperties.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/IgniteProperties.java @@ -25,8 +25,8 @@ * Ignite properties holder. */ public class IgniteProperties { - /** Properties file path. */ - private static final String FILE_PATH = "ignite.properties"; + /** Build info file path. */ + private static final String FILE_PATH = "ignite-build-info.properties"; /** Properties. */ private static final Properties PROPS; diff --git a/modules/core/src/main/java/org/apache/ignite/internal/IgniteVersionUtils.java b/modules/core/src/main/java/org/apache/ignite/internal/IgniteVersionUtils.java index 58f0887b0d593..66b7d16b5be03 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/IgniteVersionUtils.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/IgniteVersionUtils.java @@ -69,7 +69,7 @@ public class IgniteVersionUtils { BUILD_TSTAMP_FROM_PROPERTY = IgniteProperties.get("ignite.build"); - //Development ignite.properties file contains ignite.build = 0, so we will add the check for it. + //Development ignite-build-info.properties file contains ignite.build = 0, so we will add the check for it. BUILD_TSTAMP = !BUILD_TSTAMP_FROM_PROPERTY.isEmpty() && Long.parseLong(BUILD_TSTAMP_FROM_PROPERTY) != 0 ? Long.parseLong(BUILD_TSTAMP_FROM_PROPERTY) : System.currentTimeMillis() / 1000; diff --git a/modules/core/src/main/resources/ignite.properties b/modules/core/src/main/resources/ignite-build-info.properties similarity index 100% rename from modules/core/src/main/resources/ignite.properties rename to modules/core/src/main/resources/ignite-build-info.properties diff --git a/modules/core/src/test/java/org/apache/ignite/internal/util/IgniteBuildInfoPropertiesTest.java b/modules/core/src/test/java/org/apache/ignite/internal/util/IgniteBuildInfoPropertiesTest.java new file mode 100644 index 0000000000000..3844ceb55f507 --- /dev/null +++ b/modules/core/src/test/java/org/apache/ignite/internal/util/IgniteBuildInfoPropertiesTest.java @@ -0,0 +1,185 @@ +/* + * 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.ignite.internal.util; + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.io.InputStream; +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; +import java.nio.file.Files; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Enumeration; +import java.util.HashSet; +import java.util.List; +import java.util.Properties; +import java.util.Set; +import org.apache.ignite.internal.IgniteProperties; +import org.apache.ignite.internal.IgniteVersionUtils; +import org.apache.ignite.internal.util.typedef.internal.U; +import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest; +import org.jetbrains.annotations.Nullable; +import org.junit.Test; + +/** */ +public class IgniteBuildInfoPropertiesTest extends GridCommonAbstractTest { + /** */ + private static final String PROPS_CLASS = "org.apache.ignite.internal.IgniteProperties"; + + /** */ + private static final String VER_UTILS_CLASS = "org.apache.ignite.internal.IgniteVersionUtils"; + + /** */ + @Test + public void testLoadsBuildInfoProperties() { + String ver = IgniteProperties.get("ignite.version"); + String build = IgniteProperties.get("ignite.build"); + String rev = IgniteProperties.get("ignite.revision"); + String relDate = IgniteProperties.get("ignite.rel.date"); + + assertNotNull(ver); + assertNotNull(build); + assertNotNull(rev); + assertNotNull(relDate); + } + + /** */ + @Test + public void testUserIgnitePropertiesDoesNotOverrideBuildMetadata() throws Exception { + String wrongVerStr = "WRONG_VERSION"; + + File tmpDir = Files.createTempDirectory("ignite-props-test-").toFile(); + + try { + File userProps = new File(tmpDir, "ignite.properties"); + + try (FileWriter writer = new FileWriter(userProps)) { + writer.write("ignite.version=" + wrongVerStr + U.nl()); + writer.write("some.custom.property=123" + U.nl()); + } + + URL tmpUrl = tmpDir.toURI().toURL(); + + URL igniteCoreUrl = IgniteProperties.class.getProtectionDomain().getCodeSource().getLocation(); + + URL[] urls = new URL[] {tmpUrl, igniteCoreUrl}; + + ClassLoader ldr = IgniteProperties.class.getClassLoader(); + + Set urlLoadedClasses = Set.of(PROPS_CLASS, VER_UTILS_CLASS); + + try (TestURLClassLoader testLdr = new TestURLClassLoader(urls, ldr, urlLoadedClasses)) { + URL userPropsUrl = testLdr.getResource("ignite.properties"); + + assertNotNull(userPropsUrl); + + Properties props = new Properties(); + + try (InputStream in = userPropsUrl.openStream()) { + props.load(in); + } + + assertEquals(2, props.size()); + assertEquals(wrongVerStr, props.getProperty("ignite.version")); + assertEquals("123", props.getProperty("some.custom.property")); + + Class propsCls = Class.forName(PROPS_CLASS, true, testLdr); + Class utilsCls = Class.forName(VER_UTILS_CLASS, false, testLdr); + + assertSame(testLdr, propsCls.getClassLoader()); + assertSame(testLdr, utilsCls.getClassLoader()); + + assertNotNull(testLdr.getResource("ignite.properties")); + assertNotNull(testLdr.getResource("ignite-build-info.properties")); + + Method getMtd = propsCls.getMethod("get", String.class); + + String ver = (String)getMtd.invoke(null, "ignite.version"); + + assertEquals("Build metadata must not be overridden by user ignite.properties", + IgniteVersionUtils.VER_STR, ver); + } + } + finally { + U.delete(tmpDir); + } + } + + /** */ + private static class TestURLClassLoader extends URLClassLoader { + /** */ + private final Set urlLoadedClasses; + + /** */ + public TestURLClassLoader(URL[] urls, ClassLoader parent, Set urlLoadedClasses) { + super(urls, parent); + + this.urlLoadedClasses = new HashSet<>(urlLoadedClasses); + } + + /** {@inheritDoc} */ + @Override protected Class loadClass(String name, boolean resolve) throws ClassNotFoundException { + if (urlLoadedClasses.contains(name)) { + synchronized (getClassLoadingLock(name)) { + Class cls = findLoadedClass(name); + + if (cls == null) + cls = findClass(name); + + if (resolve) + resolveClass(cls); + + return cls; + } + } + + return super.loadClass(name, resolve); + } + + /** {@inheritDoc} */ + @Override public @Nullable URL getResource(String name) { + URL url = findResource(name); + + return url != null ? url : super.getResource(name); + } + + /** {@inheritDoc} */ + @Override public Enumeration getResources(String name) throws IOException { + List res = new ArrayList<>(); + + Enumeration childRes = findResources(name); + + while (childRes.hasMoreElements()) + res.add(childRes.nextElement()); + + ClassLoader parent = getParent(); + + if (parent != null) { + Enumeration parentRes = parent.getResources(name); + + while (parentRes.hasMoreElements()) + res.add(parentRes.nextElement()); + } + + return Collections.enumeration(res); + } + } +} diff --git a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteUtilSelfTestSuite.java b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteUtilSelfTestSuite.java index c06cbfe8fd4c8..0d7c413aa7eee 100644 --- a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteUtilSelfTestSuite.java +++ b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteUtilSelfTestSuite.java @@ -29,6 +29,7 @@ import org.apache.ignite.internal.util.GridConcurrentMultiPairQueueTest; import org.apache.ignite.internal.util.GridCountDownCallbackTest; import org.apache.ignite.internal.util.HostAndPortRangeTest; +import org.apache.ignite.internal.util.IgniteBuildInfoPropertiesTest; import org.apache.ignite.internal.util.IgniteDevOnlyLogTest; import org.apache.ignite.internal.util.IgniteExceptionRegistrySelfTest; import org.apache.ignite.internal.util.IgniteUtilsSelfTest; @@ -110,6 +111,7 @@ GridTransientTest.class, IgniteDevOnlyLogTest.class, GridConcurrentMultiPairQueueTest.class, + IgniteBuildInfoPropertiesTest.class, // Sensitive toString. IncludeSensitiveAtomicTest.class,