From b95e40e4f5338272fc4f716705584bed154e2541 Mon Sep 17 00:00:00 2001 From: Pavol Mederly Date: Wed, 11 Dec 2019 19:38:29 +0100 Subject: [PATCH] Rework node ID generation to Apache Conf 2.6 Fixed pom.xml changes related to Apache Commons Configuration 2.6. Cleaned up ApplicationHomeSetup and StartupConfiguration code. Fixed handling of midpoint.home throughout midPoint code. Removed TemplateEngine. It had a sad short life, really. Replaced with StringSubstitutor and ConfigurationInterpolator calls. This should (finally) resolve MID-5904. --- build-system/pom.xml | 28 +-- gui/admin-gui/pom.xml | 4 - .../boot/AbstractSpringBootApplication.java | 143 ++++++----- .../web/boot/MidPointSpringApplication.java | 10 +- .../web/security/MidPointApplication.java | 2 +- .../test/TestMidPointSpringApplication.java | 11 +- .../common/LocalizationServiceImpl.java | 2 +- .../api/MidpointConfiguration.java | 34 ++- .../midpoint/common/LocalizationTest.java | 9 +- infra/util/pom.xml | 4 + .../evolveum/midpoint/util/NetworkUtil.java | 46 ++++ .../template/AbstractChainedResolver.java | 59 ----- .../util/template/JavaPropertiesResolver.java | 38 --- .../midpoint/util/template/MapResolver.java | 41 ---- .../util/template/OsEnvironmentResolver.java | 38 --- .../util/template/ReferenceResolver.java | 29 --- .../util/template/StringSubstitutorUtil.java | 34 +++ .../util/template/TemplateEngine.java | 77 ------ .../util/template/TemplateResolution.java | 203 ---------------- .../util/TestStringSubstitutorUtil.java | 39 +++ .../midpoint/util/TestTemplateEngine.java | 98 -------- infra/util/testng-unit.xml | 2 +- model/model-impl/pom.xml | 4 + .../impl/ExtensionSchemaRestService.java | 6 +- .../impl/controller/ModelDiagController.java | 4 +- .../impl/ReportJasperCreateTaskHandler.java | 41 ++-- .../midpoint/report/impl/ReportUtils.java | 19 +- .../midpoint/wf/impl/WfConfiguration.java | 2 +- repo/repo-sql-impl/pom.xml | 2 +- .../repo/sql/SqlAuditServiceFactory.java | 4 +- .../repo/sql/SqlRepositoryConfiguration.java | 19 +- .../midpoint/init/ApplicationHomeSetup.java | 57 +++-- .../evolveum/midpoint/init/AuditFactory.java | 6 +- .../init/ConfigurableProtectorFactory.java | 5 - .../midpoint/init/StartupConfiguration.java | 162 +++++-------- .../init/interpol/HostnameLookup.java | 40 +++ .../midpoint/init/interpol/RandomLookup.java | 45 ++++ .../midpoint/init/TestConfigurationLoad.java | 24 +- repo/task-quartz-impl/pom.xml | 4 + .../task/quartzimpl/NodeIdComputer.java | 229 ++++++++---------- .../quartzimpl/TaskManagerConfiguration.java | 2 +- .../quartzimpl/cluster/NodeRegistrar.java | 33 +-- .../handlers/PartitioningTaskHandler.java | 11 +- .../task/quartzimpl/tracing/TracerImpl.java | 30 +-- .../work/workers/WorkersManager.java | 6 +- .../tools/layout/MidPointWarLauncher.java | 2 +- .../midpoint/ninja/impl/NinjaContext.java | 8 +- 47 files changed, 605 insertions(+), 1111 deletions(-) create mode 100644 infra/util/src/main/java/com/evolveum/midpoint/util/NetworkUtil.java delete mode 100644 infra/util/src/main/java/com/evolveum/midpoint/util/template/AbstractChainedResolver.java delete mode 100644 infra/util/src/main/java/com/evolveum/midpoint/util/template/JavaPropertiesResolver.java delete mode 100644 infra/util/src/main/java/com/evolveum/midpoint/util/template/MapResolver.java delete mode 100644 infra/util/src/main/java/com/evolveum/midpoint/util/template/OsEnvironmentResolver.java delete mode 100644 infra/util/src/main/java/com/evolveum/midpoint/util/template/ReferenceResolver.java create mode 100644 infra/util/src/main/java/com/evolveum/midpoint/util/template/StringSubstitutorUtil.java delete mode 100644 infra/util/src/main/java/com/evolveum/midpoint/util/template/TemplateEngine.java delete mode 100644 infra/util/src/main/java/com/evolveum/midpoint/util/template/TemplateResolution.java create mode 100644 infra/util/src/test/java/com/evolveum/midpoint/util/TestStringSubstitutorUtil.java delete mode 100644 infra/util/src/test/java/com/evolveum/midpoint/util/TestTemplateEngine.java create mode 100644 repo/system-init/src/main/java/com/evolveum/midpoint/init/interpol/HostnameLookup.java create mode 100644 repo/system-init/src/main/java/com/evolveum/midpoint/init/interpol/RandomLookup.java diff --git a/build-system/pom.xml b/build-system/pom.xml index a6ade3f5afd..8959cdf4171 100644 --- a/build-system/pom.xml +++ b/build-system/pom.xml @@ -379,11 +379,6 @@ commons-beanutils 1.9.4 - - commons-beanutils - commons-beanutils-core - 1.9.4 - commons-codec commons-codec @@ -397,21 +392,12 @@ org.apache.commons commons-configuration2 - 2.5 - - - - - - - - - - - - - - + 2.6 + + + org.apache.commons + commons-text + 1.8 commons-io @@ -1682,8 +1668,6 @@ org.apache.cxf:cxf-tools-common - - commons-beanutils:commons-beanutils-core diff --git a/gui/admin-gui/pom.xml b/gui/admin-gui/pom.xml index e6e6700af33..26a60bdb076 100644 --- a/gui/admin-gui/pom.xml +++ b/gui/admin-gui/pom.xml @@ -721,10 +721,6 @@ commons-beanutils commons-beanutils - - commons-beanutils - commons-beanutils-core - commons-javaflow commons-javaflow diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/boot/AbstractSpringBootApplication.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/boot/AbstractSpringBootApplication.java index 0d550f483ad..68f81c29db1 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/boot/AbstractSpringBootApplication.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/boot/AbstractSpringBootApplication.java @@ -27,8 +27,6 @@ import org.springframework.boot.actuate.autoconfigure.metrics.MetricsEndpointAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.metrics.SystemMetricsAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.metrics.export.simple.SimpleMetricsExportAutoConfiguration; -import org.springframework.boot.actuate.autoconfigure.metrics.jdbc.DataSourcePoolMetricsAutoConfiguration; -import org.springframework.boot.actuate.autoconfigure.metrics.orm.jpa.HibernateMetricsAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.metrics.web.servlet.WebMvcMetricsAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.metrics.web.tomcat.TomcatMetricsAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.web.servlet.ServletManagementContextAutoConfiguration; @@ -93,82 +91,77 @@ }) public abstract class AbstractSpringBootApplication extends SpringBootServletInitializer{ - private static final Trace LOGGER = TraceManager.getTrace(MidPointSpringApplication.class); - - protected static final String MIDPOINT_HOME_PROPERTY = "midpoint.home"; - protected static final String USER_HOME_PROPERTY_NAME = "user.home"; - - - @Autowired StartupConfiguration startupConfiguration; - @Autowired NodeAuthenticationEvaluator nodeAuthenticator; - - - @Bean - public ServletListenerRegistrationBean requestContextListener() { - return new ServletListenerRegistrationBean<>(new RequestContextListener()); - } - - @Bean - public FilterRegistrationBean midPointProfilingServletFilter() { - FilterRegistrationBean registration = new FilterRegistrationBean<>(); - registration.setFilter(new MidPointProfilingServletFilter()); -// registration.setDispatcherTypes(EnumSet.allOf(DispatcherType.class)); - registration.addUrlPatterns("/*"); - return registration; - } - - @Bean - public FilterRegistrationBean wicket() { - FilterRegistrationBean registration = new FilterRegistrationBean<>(); - registration.setFilter(new WicketFilter()); - registration.setDispatcherTypes(DispatcherType.ERROR, DispatcherType.REQUEST, DispatcherType.FORWARD); - registration.addUrlPatterns("/*"); - registration.addInitParameter(WicketFilter.FILTER_MAPPING_PARAM, "/*"); - registration.addInitParameter(Application.CONFIGURATION, "deployment"); // deployment development - registration.addInitParameter("applicationBean", "midpointApplication"); - registration.addInitParameter(WicketFilter.APP_FACT_PARAM, "org.apache.wicket.spring.SpringWebApplicationFactory"); - - return registration; - } - - // Overriding bean from org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration - // This method is not very clean. We should probably subclass WebSecurityConfiguration instead. - // This is the reason that global bean override is allowed in application.yml - @Bean - public FilterRegistrationBean springSecurityFilterChain() { - FilterRegistrationBean registration = new FilterRegistrationBean<>(); - registration.setFilter(new DelegatingFilterProxy()); - registration.addUrlPatterns("/*"); - return registration; - } - - @Bean - public FilterRegistrationBean webResourceOptimizer(WroFilter wroFilter) { - FilterRegistrationBean registration = new FilterRegistrationBean<>(); - registration.setFilter(wroFilter); - registration.addUrlPatterns("/wro/*"); - return registration; - } - - @Bean - public ServletRegistrationBean cxfServlet() { - ServletRegistrationBean registration = new ServletRegistrationBean<>(); - registration.setServlet(new CXFServlet()); - registration.addInitParameter("service-list-path", "midpointservices"); - registration.setLoadOnStartup(1); - registration.addUrlMappings("/model/*", "/ws/*"); - - return registration; - } - - @Bean - public ErrorPageRegistrar errorPageRegistrar() { - return new MidPointErrorPageRegistrar(); - } + private static final Trace LOGGER = TraceManager.getTrace(MidPointSpringApplication.class); + + @Autowired StartupConfiguration startupConfiguration; + @Autowired NodeAuthenticationEvaluator nodeAuthenticator; + + + @Bean + public ServletListenerRegistrationBean requestContextListener() { + return new ServletListenerRegistrationBean<>(new RequestContextListener()); + } + + @Bean + public FilterRegistrationBean midPointProfilingServletFilter() { + FilterRegistrationBean registration = new FilterRegistrationBean<>(); + registration.setFilter(new MidPointProfilingServletFilter()); + // registration.setDispatcherTypes(EnumSet.allOf(DispatcherType.class)); + registration.addUrlPatterns("/*"); + return registration; + } + + @Bean + public FilterRegistrationBean wicket() { + FilterRegistrationBean registration = new FilterRegistrationBean<>(); + registration.setFilter(new WicketFilter()); + registration.setDispatcherTypes(DispatcherType.ERROR, DispatcherType.REQUEST, DispatcherType.FORWARD); + registration.addUrlPatterns("/*"); + registration.addInitParameter(WicketFilter.FILTER_MAPPING_PARAM, "/*"); + registration.addInitParameter(Application.CONFIGURATION, "deployment"); // deployment development + registration.addInitParameter("applicationBean", "midpointApplication"); + registration.addInitParameter(WicketFilter.APP_FACT_PARAM, "org.apache.wicket.spring.SpringWebApplicationFactory"); + + return registration; + } + + // Overriding bean from org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration + // This method is not very clean. We should probably subclass WebSecurityConfiguration instead. + // This is the reason that global bean override is allowed in application.yml + @Bean + public FilterRegistrationBean springSecurityFilterChain() { + FilterRegistrationBean registration = new FilterRegistrationBean<>(); + registration.setFilter(new DelegatingFilterProxy()); + registration.addUrlPatterns("/*"); + return registration; + } + + @Bean + public FilterRegistrationBean webResourceOptimizer(WroFilter wroFilter) { + FilterRegistrationBean registration = new FilterRegistrationBean<>(); + registration.setFilter(wroFilter); + registration.addUrlPatterns("/wro/*"); + return registration; + } + + @Bean + public ServletRegistrationBean cxfServlet() { + ServletRegistrationBean registration = new ServletRegistrationBean<>(); + registration.setServlet(new CXFServlet()); + registration.addInitParameter("service-list-path", "midpointservices"); + registration.setLoadOnStartup(1); + registration.addUrlMappings("/model/*", "/ws/*"); + + return registration; + } + + @Bean + public ErrorPageRegistrar errorPageRegistrar() { + return new MidPointErrorPageRegistrar(); + } @Bean public SessionRegistry sessionRegistry() { return new SessionRegistryImpl(); } - } diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/boot/MidPointSpringApplication.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/boot/MidPointSpringApplication.java index b7ae4ddee84..73c7ed852bf 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/boot/MidPointSpringApplication.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/boot/MidPointSpringApplication.java @@ -7,6 +7,7 @@ package com.evolveum.midpoint.web.boot; +import com.evolveum.midpoint.common.configuration.api.MidpointConfiguration; import com.evolveum.midpoint.gui.impl.factory.TextAreaPanelFactory; import com.evolveum.midpoint.gui.impl.registry.GuiComponentRegistryImpl; import com.evolveum.midpoint.util.logging.Trace; @@ -128,16 +129,17 @@ protected SpringApplicationBuilder configure(SpringApplicationBuilder applicatio } private static SpringApplicationBuilder configureApplication(SpringApplicationBuilder application) { - String mpHome = System.getProperty(MIDPOINT_HOME_PROPERTY); + String mpHome = System.getProperty(MidpointConfiguration.MIDPOINT_HOME_PROPERTY); if (StringUtils.isEmpty(mpHome)) { - LOGGER.info("{} system property is not set, using default configuration", MIDPOINT_HOME_PROPERTY); + LOGGER.info("{} system property is not set, using default configuration", + MidpointConfiguration.MIDPOINT_HOME_PROPERTY); - mpHome = System.getProperty(USER_HOME_PROPERTY_NAME); + mpHome = System.getProperty(MidpointConfiguration.USER_HOME_PROPERTY); if (!mpHome.endsWith("/")) { mpHome += "/"; } mpHome += "midpoint"; - System.setProperty(MIDPOINT_HOME_PROPERTY, mpHome); + System.setProperty(MidpointConfiguration.MIDPOINT_HOME_PROPERTY, mpHome); } System.setProperty("spring.config.additional-location", "${midpoint.home}/"); diff --git a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/security/MidPointApplication.java b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/security/MidPointApplication.java index 7eb897fadc5..0460c078a19 100644 --- a/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/security/MidPointApplication.java +++ b/gui/admin-gui/src/main/java/com/evolveum/midpoint/web/security/MidPointApplication.java @@ -389,7 +389,7 @@ private void initializeSchrodinger() { } String value = environment.getProperty(MidpointConfiguration.MIDPOINT_SCHRODINGER_PROPERTY); - Boolean enabled = Boolean.parseBoolean(value); + boolean enabled = Boolean.parseBoolean(value); if (enabled) { LOGGER.info("Schrodinger plugin enabled"); diff --git a/gui/admin-gui/src/test/java/com/evolveum/midpoint/gui/test/TestMidPointSpringApplication.java b/gui/admin-gui/src/test/java/com/evolveum/midpoint/gui/test/TestMidPointSpringApplication.java index 64e680b4642..84d91ec8a03 100644 --- a/gui/admin-gui/src/test/java/com/evolveum/midpoint/gui/test/TestMidPointSpringApplication.java +++ b/gui/admin-gui/src/test/java/com/evolveum/midpoint/gui/test/TestMidPointSpringApplication.java @@ -8,6 +8,7 @@ import java.lang.management.ManagementFactory; +import com.evolveum.midpoint.common.configuration.api.MidpointConfiguration; import org.apache.commons.lang.StringUtils; import org.springframework.boot.Banner; import org.springframework.boot.ExitCodeGenerator; @@ -24,7 +25,6 @@ import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; import com.evolveum.midpoint.web.boot.AbstractSpringBootApplication; -import com.evolveum.midpoint.web.boot.MidPointSpringApplication; /** * @author katka @@ -107,16 +107,17 @@ protected SpringApplicationBuilder configure(SpringApplicationBuilder applicatio //what is this for? why static? private static SpringApplicationBuilder configureApplication(SpringApplicationBuilder application) { - String mpHome = System.getProperty(MIDPOINT_HOME_PROPERTY); + String mpHome = System.getProperty(MidpointConfiguration.MIDPOINT_HOME_PROPERTY); if (StringUtils.isEmpty(mpHome)) { - LOGGER.info("{} system property is not set, using default configuration", MIDPOINT_HOME_PROPERTY); + LOGGER.info("{} system property is not set, using default configuration", + MidpointConfiguration.MIDPOINT_HOME_PROPERTY); - mpHome = System.getProperty(USER_HOME_PROPERTY_NAME); + mpHome = System.getProperty(MidpointConfiguration.USER_HOME_PROPERTY); if (!mpHome.endsWith("/")) { mpHome += "/"; } mpHome += "midpoint"; - System.setProperty(MIDPOINT_HOME_PROPERTY, mpHome); + System.setProperty(MidpointConfiguration.MIDPOINT_HOME_PROPERTY, mpHome); } System.setProperty("spring.config.additional-location", "${midpoint.home}/"); diff --git a/infra/common/src/main/java/com/evolveum/midpoint/common/LocalizationServiceImpl.java b/infra/common/src/main/java/com/evolveum/midpoint/common/LocalizationServiceImpl.java index 09a8d6f1476..f4f397e7112 100644 --- a/infra/common/src/main/java/com/evolveum/midpoint/common/LocalizationServiceImpl.java +++ b/infra/common/src/main/java/com/evolveum/midpoint/common/LocalizationServiceImpl.java @@ -166,7 +166,7 @@ private ResourceBundleMessageSource buildSource(String basename, ClassLoader cla } private URL buildMidpointHomeLocalizationFolderUrl() { - String midpointHome = System.getProperty("midpoint.home"); + String midpointHome = System.getProperty(MidpointConfiguration.MIDPOINT_HOME_PROPERTY); File file = new File(midpointHome, "localization"); try { diff --git a/infra/common/src/main/java/com/evolveum/midpoint/common/configuration/api/MidpointConfiguration.java b/infra/common/src/main/java/com/evolveum/midpoint/common/configuration/api/MidpointConfiguration.java index 28fba0b8c38..62503403f64 100644 --- a/infra/common/src/main/java/com/evolveum/midpoint/common/configuration/api/MidpointConfiguration.java +++ b/infra/common/src/main/java/com/evolveum/midpoint/common/configuration/api/MidpointConfiguration.java @@ -12,15 +12,19 @@ /** * @author mamut */ - public interface MidpointConfiguration { // Names of system properties. Note that they are also copied into config.xml-loaded configuration. String MIDPOINT_SILENT_PROPERTY = "midpoint.silent"; String MIDPOINT_HOME_PROPERTY = "midpoint.home"; + String MIDPOINT_SCHRODINGER_PROPERTY = "midpoint.schrodinger"; String MIDPOINT_LOGGING_ALT_ENABLED_PROPERTY = "midpoint.logging.alt.enabled"; String MIDPOINT_LOGGING_ALT_FILENAME_PROPERTY = "midpoint.logging.alt.filename"; String MIDPOINT_LOGGING_ALT_PREFIX_PROPERTY = "midpoint.logging.alt.prefix"; + + String USER_HOME_PROPERTY = "user.home"; + + // Other commonly-used configuration properties String MIDPOINT_NODE_ID_PROPERTY = "midpoint.nodeId"; String MIDPOINT_NODE_ID_EXPRESSION_PROPERTY = "midpoint.nodeIdExpression"; String MIDPOINT_NODE_ID_SOURCE_PROPERTY = "midpoint.nodeIdSource"; @@ -29,11 +33,7 @@ public interface MidpointConfiguration { String MIDPOINT_HOST_NAME_PROPERTY = "midpoint.hostName"; String MIDPOINT_HTTP_PORT_PROPERTY = "midpoint.httpPort"; - // TODO read these from the MidpointConfiguration instead of system properties. - // It will provide greater flexibility, as the administrator will be able to set them permanently in config.xml. - String MIDPOINT_SCHRODINGER_PROPERTY = "midpoint.schrodinger"; - - // names of configuration sections + // Names of configuration sections String AUDIT_CONFIGURATION = "midpoint.audit"; String SYSTEM_CONFIGURATION = "midpoint.system"; String GLOBAL_CONFIGURATION = "midpoint.global"; @@ -55,6 +55,9 @@ public interface MidpointConfiguration { */ String MIDPOINT_SYSTEM_PROPERTIES_BASE_PATH = "midpoint-system"; + /** + * @return midPoint home directory. Currently it is the same value as in "midpoint.home" system property. + */ String getMidpointHome(); /** @@ -65,8 +68,7 @@ public interface MidpointConfiguration { * Samples of names: *
  • *
      repository -> midpoint.repository
    - *
      provisioning -> midpoint.provisioning
    - *
      model -> midpoint.model
    + *
      provisioning -> midpoint.provisioning
    *
  • * * @return Configuration object @@ -74,18 +76,32 @@ public interface MidpointConfiguration { */ Configuration getConfiguration(String component); + /** + * @return Global configuration. + */ Configuration getConfiguration(); + /** + * @return True if we are running in safe mode (the exact meaning gradually evolves; but the overall idea is to make + * midPoint barely usable to be able to fix the worst problems preventing it from running normally). + */ boolean isSafeMode(); /** - * @return true if the profiling interceptor should be loaded + * @return True if the profiling interceptor should be loaded. */ + @SuppressWarnings("unused") // It is actually used from ctx-interceptor.xml boolean isProfilingEnabled(); + /** + * @return Current profiling mode e.g. on, off, dynamic. + */ @NotNull ProfilingMode getProfilingMode(); + /** + * @return "midpoint.system" section of the system configuration + */ @NotNull SystemConfigurationSection getSystemSection(); } diff --git a/infra/common/src/test/java/com/evolveum/midpoint/common/LocalizationTest.java b/infra/common/src/test/java/com/evolveum/midpoint/common/LocalizationTest.java index 880bd16acf6..6fe3e4606ad 100644 --- a/infra/common/src/test/java/com/evolveum/midpoint/common/LocalizationTest.java +++ b/infra/common/src/test/java/com/evolveum/midpoint/common/LocalizationTest.java @@ -7,6 +7,7 @@ package com.evolveum.midpoint.common; +import com.evolveum.midpoint.common.configuration.api.MidpointConfiguration; import com.evolveum.midpoint.util.LocalizableMessage; import com.evolveum.midpoint.util.LocalizableMessageBuilder; import org.testng.AssertJUnit; @@ -22,20 +23,18 @@ */ public class LocalizationTest { - private static final String MIDPOINT_HOME_PROPERTY = "midpoint.home"; - private static String midpointHome; private static LocalizationServiceImpl service; @BeforeClass public static void beforeClass() { - midpointHome = System.getProperty(MIDPOINT_HOME_PROPERTY); + midpointHome = System.getProperty(MidpointConfiguration.MIDPOINT_HOME_PROPERTY); File file = new File("."); String newMidpointHome = file.getAbsolutePath() + "/fake-midpoint-home"; - System.setProperty(MIDPOINT_HOME_PROPERTY, newMidpointHome); + System.setProperty(MidpointConfiguration.MIDPOINT_HOME_PROPERTY, newMidpointHome); service = new LocalizationServiceImpl(); service.init(); @@ -43,7 +42,7 @@ public static void beforeClass() { @AfterClass public static void afterClass() { - System.setProperty(MIDPOINT_HOME_PROPERTY, midpointHome); + System.setProperty(MidpointConfiguration.MIDPOINT_HOME_PROPERTY, midpointHome); } @Test diff --git a/infra/util/pom.xml b/infra/util/pom.xml index 0dc9d9f9b17..06b4fbccea7 100644 --- a/infra/util/pom.xml +++ b/infra/util/pom.xml @@ -55,6 +55,10 @@ org.apache.commons commons-lang3
    + + org.apache.commons + commons-text + diff --git a/infra/util/src/main/java/com/evolveum/midpoint/util/NetworkUtil.java b/infra/util/src/main/java/com/evolveum/midpoint/util/NetworkUtil.java new file mode 100644 index 00000000000..46020ca073c --- /dev/null +++ b/infra/util/src/main/java/com/evolveum/midpoint/util/NetworkUtil.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2019 Evolveum and contributors + * + * This work is dual-licensed under the Apache License 2.0 + * and European Union Public License. See LICENSE file for details. + */ + +package com.evolveum.midpoint.util; + +import org.apache.commons.lang.StringUtils; +import org.jetbrains.annotations.Nullable; + +import java.net.InetAddress; +import java.net.UnknownHostException; + +public class NetworkUtil { + + @Nullable + public static String getLocalHostNameFromOperatingSystem() throws UnknownHostException { + // Not entirely correct. But we have no other option here + // other than go native or execute a "hostname" shell command. + // We do not want to do neither. + InetAddress localHost = InetAddress.getLocalHost(); + if (localHost == null) { + String hostname = System.getenv("HOSTNAME"); // Unix + if (StringUtils.isNotEmpty(hostname)) { + return hostname; + } + hostname = System.getenv("COMPUTERNAME"); // Windows + if (StringUtils.isNotEmpty(hostname)) { + return hostname; + } + return null; + } + + String hostname = localHost.getCanonicalHostName(); + if (StringUtils.isNotEmpty(hostname)) { + return hostname; + } + hostname = localHost.getHostName(); + if (StringUtils.isNotEmpty(hostname)) { + return hostname; + } + return localHost.getHostAddress(); + } +} diff --git a/infra/util/src/main/java/com/evolveum/midpoint/util/template/AbstractChainedResolver.java b/infra/util/src/main/java/com/evolveum/midpoint/util/template/AbstractChainedResolver.java deleted file mode 100644 index 713cb30a660..00000000000 --- a/infra/util/src/main/java/com/evolveum/midpoint/util/template/AbstractChainedResolver.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (c) 2019 Evolveum and contributors - * - * This work is dual-licensed under the Apache License 2.0 - * and European Union Public License. See LICENSE file for details. - */ - -package com.evolveum.midpoint.util.template; - -import org.jetbrains.annotations.NotNull; - -import java.util.Collection; -import java.util.List; - -/** - * Resolver that is able to call upstream if it cannot resolve a reference. - */ -public abstract class AbstractChainedResolver implements ReferenceResolver { - - /** - * Resolver to call if we are unable to help. - */ - private final ReferenceResolver upstreamResolver; - - /** - * Whether this resolver is engaged in resolving references in default (null) scope. - */ - private final boolean actsAsDefault; - - public AbstractChainedResolver(ReferenceResolver upstreamResolver, boolean actsAsDefault) { - this.upstreamResolver = upstreamResolver; - this.actsAsDefault = actsAsDefault; - } - - protected abstract String resolveLocally(String reference, List parameters); - - @NotNull - protected abstract Collection getScopes(); - - @Override - public String resolve(String scope, String reference, @NotNull List parameters) { - if (isScopeApplicable(scope)) { - String resolution = resolveLocally(reference, parameters); - if (resolution != null) { - return resolution; - } - } - - if (upstreamResolver != null) { - return upstreamResolver.resolve(scope, reference, parameters); - } else { - return null; - } - } - - private boolean isScopeApplicable(String scope) { - return actsAsDefault && scope == null || getScopes().contains(scope); - } -} diff --git a/infra/util/src/main/java/com/evolveum/midpoint/util/template/JavaPropertiesResolver.java b/infra/util/src/main/java/com/evolveum/midpoint/util/template/JavaPropertiesResolver.java deleted file mode 100644 index 61cae00f004..00000000000 --- a/infra/util/src/main/java/com/evolveum/midpoint/util/template/JavaPropertiesResolver.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (c) 2019 Evolveum and contributors - * - * This work is dual-licensed under the Apache License 2.0 - * and European Union Public License. See LICENSE file for details. - */ - -package com.evolveum.midpoint.util.template; - -import org.jetbrains.annotations.NotNull; - -import java.util.Collection; -import java.util.Collections; -import java.util.List; - -/** - * Resolves references using Java system properties. - */ -public class JavaPropertiesResolver extends AbstractChainedResolver { - - @SuppressWarnings("WeakerAccess") - public static final String SCOPE = "prop"; - - public JavaPropertiesResolver(ReferenceResolver upstreamResolver, boolean actsAsDefault) { - super(upstreamResolver, actsAsDefault); - } - - @Override - protected String resolveLocally(String reference, List parameters) { - return System.getProperty(reference); - } - - @NotNull - @Override - protected Collection getScopes() { - return Collections.singletonList(SCOPE); - } -} diff --git a/infra/util/src/main/java/com/evolveum/midpoint/util/template/MapResolver.java b/infra/util/src/main/java/com/evolveum/midpoint/util/template/MapResolver.java deleted file mode 100644 index 436bbd3bb8a..00000000000 --- a/infra/util/src/main/java/com/evolveum/midpoint/util/template/MapResolver.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2019 Evolveum and contributors - * - * This work is dual-licensed under the Apache License 2.0 - * and European Union Public License. See LICENSE file for details. - */ - -package com.evolveum.midpoint.util.template; - -import org.jetbrains.annotations.NotNull; - -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Map; - -/** - * Resolves references using externally provided map. - */ -public class MapResolver extends AbstractChainedResolver { - - private final String myScope; - private final Map map; - - public MapResolver(ReferenceResolver upstreamResolver, boolean actsAsDefault, String myScope, Map map) { - super(upstreamResolver, actsAsDefault); - this.myScope = myScope; - this.map = map; - } - - @Override - protected String resolveLocally(String reference, List parameters) { - return map.get(reference); - } - - @NotNull - @Override - protected Collection getScopes() { - return myScope != null ? Collections.singleton(myScope) : Collections.emptySet(); - } -} diff --git a/infra/util/src/main/java/com/evolveum/midpoint/util/template/OsEnvironmentResolver.java b/infra/util/src/main/java/com/evolveum/midpoint/util/template/OsEnvironmentResolver.java deleted file mode 100644 index 027302840a9..00000000000 --- a/infra/util/src/main/java/com/evolveum/midpoint/util/template/OsEnvironmentResolver.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (c) 2019 Evolveum and contributors - * - * This work is dual-licensed under the Apache License 2.0 - * and European Union Public License. See LICENSE file for details. - */ - -package com.evolveum.midpoint.util.template; - -import org.jetbrains.annotations.NotNull; - -import java.util.Collection; -import java.util.Collections; -import java.util.List; - -/** - * Resolves references using operating system environment variables. - */ -public class OsEnvironmentResolver extends AbstractChainedResolver { - - @SuppressWarnings("WeakerAccess") - public static final String SCOPE = "env"; - - public OsEnvironmentResolver(ReferenceResolver upstreamResolver, boolean actsAsDefault) { - super(upstreamResolver, actsAsDefault); - } - - @Override - protected String resolveLocally(String reference, List parameters) { - return System.getenv(reference); - } - - @NotNull - @Override - protected Collection getScopes() { - return Collections.singleton(SCOPE); - } -} diff --git a/infra/util/src/main/java/com/evolveum/midpoint/util/template/ReferenceResolver.java b/infra/util/src/main/java/com/evolveum/midpoint/util/template/ReferenceResolver.java deleted file mode 100644 index ed97a32ae36..00000000000 --- a/infra/util/src/main/java/com/evolveum/midpoint/util/template/ReferenceResolver.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (c) 2019 Evolveum and contributors - * - * This work is dual-licensed under the Apache License 2.0 - * and European Union Public License. See LICENSE file for details. - */ - -package com.evolveum.midpoint.util.template; - -import org.jetbrains.annotations.NotNull; - -import java.util.List; - -/** - * Resolver of references in templates. - */ -@FunctionalInterface -public interface ReferenceResolver { - - /** - * Returns resolved value of the reference. - * - * @param scope Scope e.g. null meaning default scope, "env" meaning environment variables, "" meaning built-in references etc. - * @param reference Reference name e.g. "seq" - * @param parameters Reference parameters e.g. "%04d" - * @return Resolved reference value e.g. "0003" - */ - String resolve(String scope, String reference, @NotNull List parameters); -} diff --git a/infra/util/src/main/java/com/evolveum/midpoint/util/template/StringSubstitutorUtil.java b/infra/util/src/main/java/com/evolveum/midpoint/util/template/StringSubstitutorUtil.java new file mode 100644 index 00000000000..bc56ef7dfc4 --- /dev/null +++ b/infra/util/src/main/java/com/evolveum/midpoint/util/template/StringSubstitutorUtil.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2019 Evolveum and contributors + * + * This work is dual-licensed under the Apache License 2.0 + * and European Union Public License. See LICENSE file for details. + */ +package com.evolveum.midpoint.util.template; + +import org.apache.commons.text.StringSubstitutor; +import org.jetbrains.annotations.NotNull; + +import java.util.Map; + +/** + * Utility methods for string substitution needs in midPoint. Uses Apache Commons Text StringSubstitutor. + * (Of course, you can - and perhaps should - call StringSubstitutor directly in the code. Here we provide + * some commonly-used methods that require custom configuration of the substitutor.) + */ +public class StringSubstitutorUtil { + + /** + * Evaluates a template against set of replacement mappings. + * The string(s) to be matched are denoted by "{key}" sequence(s). + * + * This is a legacy method. We should use the "$" sign in the future. + * + * @param template Template e.g. "{masterTaskName} ({index})" + * @param replacements Map of e.g. "masterTaskName" -> "Reconciliation", "index" -> "1" + * @return resolved template, e.g. "Reconciliation (1)" + */ + public static String simpleExpand(String template, @NotNull Map replacements) { + return new StringSubstitutor(replacements, "{", "}").replace(template); + } +} diff --git a/infra/util/src/main/java/com/evolveum/midpoint/util/template/TemplateEngine.java b/infra/util/src/main/java/com/evolveum/midpoint/util/template/TemplateEngine.java deleted file mode 100644 index 5e679e3decd..00000000000 --- a/infra/util/src/main/java/com/evolveum/midpoint/util/template/TemplateEngine.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (c) 2019 Evolveum and contributors - * - * This work is dual-licensed under the Apache License 2.0 - * and European Union Public License. See LICENSE file for details. - */ -package com.evolveum.midpoint.util.template; - -import org.jetbrains.annotations.NotNull; - -import java.util.Map; - -/** - * Generic template expansion engine. - * - * Beyond simple references like $ref it supports scoped and parameterized expressions in the form of ${scope:ref(parameters)}. - * Allows the use of '\' as a general escaping character (e.g. for "$" sign, for brackets, colons, quotes, etc). - */ -public class TemplateEngine { - - /** - * Resolver of the references. - */ - private final ReferenceResolver resolver; - - /** - * If true, expressions are marked as ${...}. This is the recommended way. - * If false, legacy marking of {...} is used. - */ - private final boolean useExpressionStartCharacter; - - /** - * If a reference cannot be resolved, should we throw an error (true), or silently replace it with an empty string (false)? - */ - private final boolean errorOnUnresolved; - - public TemplateEngine(ReferenceResolver resolver, boolean useExpressionStartCharacter, boolean errorOnUnresolved) { - this.resolver = resolver; - this.useExpressionStartCharacter = useExpressionStartCharacter; - this.errorOnUnresolved = errorOnUnresolved; - } - - /** - * Generic templating function. - * - * @param template Template e.g. node-${builtin:seq(%04d)} - * @return resolved template e.g. node-0003 - */ - public String expand(String template) { - return new TemplateResolution(template, resolver, useExpressionStartCharacter, errorOnUnresolved).resolve(); - } - - /** - * Simply expands ${propertyName} Java system properties. - */ - public static String simpleExpandProperties(String template) { - JavaPropertiesResolver resolver = new JavaPropertiesResolver(null, true); - TemplateEngine engine = new TemplateEngine(resolver, true, false); - return engine.expand(template); - } - - /** - * Evaluates a template against set of replacement mappings. - * The string(s) to be matched are denoted by "{key}" sequence(s). - * - * This is a legacy method. We should use the "$" sign in the future. - * - * @param template Template e.g. "{masterTaskName} ({index})" - * @param replacements Map of e.g. "masterTaskName" -> "Reconciliation", "index" -> "1" - * @return resolved template, e.g. "Reconciliation (1)" - */ - public static String simpleExpand(String template, @NotNull Map replacements) { - MapResolver resolver = new MapResolver(null, true, null, replacements); - TemplateEngine engine = new TemplateEngine(resolver, false, false); - return engine.expand(template); - } -} diff --git a/infra/util/src/main/java/com/evolveum/midpoint/util/template/TemplateResolution.java b/infra/util/src/main/java/com/evolveum/midpoint/util/template/TemplateResolution.java deleted file mode 100644 index aa6b73c20b6..00000000000 --- a/infra/util/src/main/java/com/evolveum/midpoint/util/template/TemplateResolution.java +++ /dev/null @@ -1,203 +0,0 @@ -/* - * Copyright (c) 2019 Evolveum and contributors - * - * This work is dual-licensed under the Apache License 2.0 - * and European Union Public License. See LICENSE file for details. - */ - -package com.evolveum.midpoint.util.template; - -import org.jetbrains.annotations.NotNull; - -import java.util.ArrayList; -import java.util.List; - -import static java.util.Collections.emptyList; - -/** - * Represents a state in template resolution process. - */ -class TemplateResolution { - - private static final char SCOPE_DELIMITER = ':'; - private static final char EXPRESSION_START_CHARACTER = '$'; - - // Configuration - @NotNull private final String template; - @NotNull private final ReferenceResolver resolver; - private final boolean useExpressionStartCharacter; - private final boolean errorOnUnresolved; - - // State - private StringBuilder result = new StringBuilder(); - private int position = 0; - private int errorReportingSegmentStart; - - TemplateResolution(@NotNull String template, @NotNull ReferenceResolver resolver, boolean useExpressionStartCharacter, - boolean errorOnUnresolved) { - this.template = template; - this.resolver = resolver; - this.useExpressionStartCharacter = useExpressionStartCharacter; - this.errorOnUnresolved = errorOnUnresolved; - } - - String resolve() { - while (position < template.length()) { - char current = template.charAt(position); - if (position < template.length() - 1) { - char next = template.charAt(position + 1); - if (current == '\\') { - result.append(next); - position++; - } else if (useExpressionStartCharacter && current == EXPRESSION_START_CHARACTER && next != '{') { - resolveSimpleReference(); - } else if (useExpressionStartCharacter && current == EXPRESSION_START_CHARACTER || - !useExpressionStartCharacter && current == '{') { - resolveComplexReference(); - } else { - result.append(current); - position++; - } - } else { - // whatever the last character is, let's output it - result.append(current); - position++; - } - } - return result.toString(); - } - - private void resolveSimpleReference() { - int start = ++position; - while (position < template.length() && isReferenceChar(template.charAt(position))) { - position++; - } - if (position > start) { - String reference = template.substring(start, position); - resolveAndAppend(null, reference, emptyList()); - } else { - result.append(EXPRESSION_START_CHARACTER); - } - } - - /** - * Resolves something like ${scope:ref(parameters)} (with scope and parameters being optional). - * - * parameters = parameter1,parameter2,...,parameterN - * where each parameter is either a plain string (except for comma and ')') or quoted string - in single or double quotes - */ - private void resolveComplexReference() { - errorReportingSegmentStart = position; - if (useExpressionStartCharacter) { - position += 2; - } else { - position += 1; - } - StringBuilder currentSegment = new StringBuilder(); - String scope = null; - String reference = null; - List parameters = new ArrayList<>(); - for (; position < template.length(); position++) { - char current = template.charAt(position); - if (current == '\\') { - position++; - if (position == template.length()) { - currentSegment.append(current); // What else? It will end up wrong anyway, as we should close with '}' - } else { - currentSegment.append(template.charAt(position)); - } - } else if (scope == null && current == SCOPE_DELIMITER) { - scope = currentSegment.toString().trim(); - currentSegment.setLength(0); - } else if (current == '(' || current == '}') { - reference = currentSegment.toString().trim(); - if (current == '(') { - position++; - parseParameters(parameters); - } - break; - } else { - currentSegment.append(current); - } - } - skipWhitespaces(); - if (position < template.length() && template.charAt(position) == '}') { - resolveAndAppend(scope, reference, parameters); - position++; - } else { - throw new IllegalArgumentException("Unfinished reference: " + template.substring(errorReportingSegmentStart)); - } - } - - private void parseParameters(List parameters) { - while (position < template.length()) { - char current = template.charAt(position); - if (Character.isWhitespace(current)) { - position++; - } else if (current == ')') { - position++; - break; - } else if (current == '\'' || current == '\"') { - //noinspection UnnecessaryLocalVariable - char border = current; - position++; - StringBuilder parameter = new StringBuilder(); - while (position < template.length()) { - char c = template.charAt(position++); - if (c == border) { - parameters.add(parameter.toString()); - skipWhitespaces(); - if (position < template.length()) { - char separator = template.charAt(position++); - if (separator == ')') { - return; - } else if (separator == ',') { - break; - } else { - throw new IllegalArgumentException("Unexpected content after parameter: " + template.substring(errorReportingSegmentStart, position)); - } - } - } else { - parameter.append(c); - } - } - } else { - StringBuilder parameter = new StringBuilder(); - while (position < template.length()) { - char c = template.charAt(position++); - if (c == ',' || c == ')') { - parameters.add(parameter.toString().trim()); - if (c == ')') { - return; - } else { - break; - } - } else { - parameter.append(c); - } - } - } - } - } - - private void skipWhitespaces() { - while (position < template.length() && Character.isWhitespace(template.charAt(position))) { - position++; - } - } - - private boolean isReferenceChar(char c) { - return Character.isLetterOrDigit(c) || c == '.' || c == '_' || c == '-'; - } - - private void resolveAndAppend(String scope, String reference, @NotNull List parameters) { - String resolved = resolver.resolve(scope, reference, parameters); - if (resolved != null) { - result.append(resolved); - } else if (errorOnUnresolved) { - throw new IllegalStateException("Reference '" + reference + "' in scope '" + scope + "' couldn't be resolved"); - } else { - // silently ignore - } - } -} diff --git a/infra/util/src/test/java/com/evolveum/midpoint/util/TestStringSubstitutorUtil.java b/infra/util/src/test/java/com/evolveum/midpoint/util/TestStringSubstitutorUtil.java new file mode 100644 index 00000000000..e6c96c1ee54 --- /dev/null +++ b/infra/util/src/test/java/com/evolveum/midpoint/util/TestStringSubstitutorUtil.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2019 Evolveum and contributors + * + * This work is dual-licensed under the Apache License 2.0 + * and European Union Public License. See LICENSE file for details. + */ +package com.evolveum.midpoint.util; + +import com.evolveum.midpoint.util.template.*; +import org.testng.annotations.Test; + +import java.util.*; + +import static org.testng.AssertJUnit.*; + +public class TestStringSubstitutorUtil { + + @Test + public void testSimpleExpand() { + System.out.println("===[ testSimpleExpand ]==="); + Map map = new HashMap<>(); + map.put("t1", "TEST1"); + map.put("t2", "TEST2"); + + assertSimpleExpand(map, "", ""); + assertSimpleExpand(map, "abc", "abc"); + assertSimpleExpand(map, "{t1}", "TEST1"); + assertSimpleExpand(map, "{t3}", "{t3}"); + assertSimpleExpand(map, "abc{t1}", "abcTEST1"); + assertSimpleExpand(map, "abc{t1}def", "abcTEST1def"); + assertSimpleExpand(map, "{t1}{t2}", "TEST1TEST2"); + } + + private void assertSimpleExpand(Map map, String template, String expected) { + String result = StringSubstitutorUtil.simpleExpand(template, map); + System.out.println(template + " => " + result); + assertEquals("Wrong result", expected, result); + } +} diff --git a/infra/util/src/test/java/com/evolveum/midpoint/util/TestTemplateEngine.java b/infra/util/src/test/java/com/evolveum/midpoint/util/TestTemplateEngine.java deleted file mode 100644 index 8686314a47e..00000000000 --- a/infra/util/src/test/java/com/evolveum/midpoint/util/TestTemplateEngine.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright (c) 2019 Evolveum and contributors - * - * This work is dual-licensed under the Apache License 2.0 - * and European Union Public License. See LICENSE file for details. - */ -package com.evolveum.midpoint.util; - -import com.evolveum.midpoint.util.template.*; -import org.jetbrains.annotations.NotNull; -import org.testng.annotations.Test; - -import java.util.*; - -import static org.testng.AssertJUnit.*; - -public class TestTemplateEngine { - - @Test - public void testTemplateWithJavaProperties() { - System.out.println("===[ testTemplateWithJavaProperties ]==="); - System.setProperty("t1", "TEST1"); - System.setProperty("t2", "TEST2"); - - ReferenceResolver resolver = new JavaPropertiesResolver(null, true); - TemplateEngine engine = new TemplateEngine(resolver, true, false); - assertExpand(engine, "", ""); - assertExpand(engine, "abc", "abc"); - assertExpand(engine, "${t1}", "TEST1"); - assertExpand(engine, "${t3}", ""); - assertExpand(engine, "$t1", "TEST1"); - assertExpand(engine, "$t1 $t2", "TEST1 TEST2"); - assertExpand(engine, "abc${t1}", "abcTEST1"); - assertExpand(engine, "abc${t1}def", "abcTEST1def"); - assertExpand(engine, "${t1}${t2}", "TEST1TEST2"); - assertExpand(engine, "${prop:t1} ${prop:t2()}", "TEST1 TEST2"); - assertExpand(engine, "${prop:t1(abc)} ${prop:t2('abc')}", "TEST1 TEST2"); - assertExpand(engine, "${prop:t1(abc)} ${prop:t2('abc\\}')}", "TEST1 TEST2"); - assertError(engine, "${t1", "Unfinished reference"); - assertError(engine, "abc${t1", "Unfinished reference"); - assertError(engine, "${t1('abc", "Unfinished reference"); - assertError(engine, "${t1('abc' abc", "Unexpected content after parameter"); - } - - @Test - public void testTemplateWithBuiltin() { - System.out.println("===[ testTemplateWithBuiltin ]==="); - Map resolutionMap = new HashMap<>(); - resolutionMap.put("k1", "Key1"); - resolutionMap.put("k2", "Key2"); - - AbstractChainedResolver builtinResolver = new AbstractChainedResolver(null, false) { - @Override - protected String resolveLocally(String reference, List parameters) { - if ("concat".equals(reference)) { - return String.join("+", parameters); - } else { - return null; - } - } - - @NotNull - @Override - protected Collection getScopes() { - return Collections.singleton(""); - } - }; - ReferenceResolver resolver = new MapResolver(builtinResolver, true, "map", resolutionMap); - - TemplateEngine engine = new TemplateEngine(resolver, true, true); - assertExpand(engine, "", ""); - assertExpand(engine, "abc", "abc"); - assertExpand(engine, "${k1}", "Key1"); - assertExpand(engine, "${:concat}", ""); - assertExpand(engine, "x${:concat(a,'b','',d)}x", "xa+b++dx"); - assertExpand(engine, "x${ : concat ( a, 'b', ' ', d)}x", "xa+b+ +dx"); - assertError(engine, "${wrong}", "couldn't be resolved"); - } - - private void assertExpand(TemplateEngine engine, String template, String expected) { - String result = engine.expand(template); - System.out.println(template + " => " + result); - assertEquals("Wrong result", expected, result); - } - - private void assertError(TemplateEngine engine, String template, String expected) { - try { - String result = engine.expand(template); - fail("Unexpected success with result=" + result); - } catch (RuntimeException e) { - if (e.getMessage().contains(expected)) { - System.out.println("Got expected exception: " + e.getMessage()); - } else { - throw new AssertionError("Got unexpected exception: " + e.getMessage(), e); - } - } - } -} diff --git a/infra/util/testng-unit.xml b/infra/util/testng-unit.xml index 464347988f7..d46452b5700 100644 --- a/infra/util/testng-unit.xml +++ b/infra/util/testng-unit.xml @@ -25,7 +25,7 @@ - + diff --git a/model/model-impl/pom.xml b/model/model-impl/pom.xml index fb4dd43609b..c7857cff2c2 100644 --- a/model/model-impl/pom.xml +++ b/model/model-impl/pom.xml @@ -179,6 +179,10 @@ org.apache.commons commons-collections4
    + + org.apache.commons + commons-text + org.apache.cxf cxf-core diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/ExtensionSchemaRestService.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/ExtensionSchemaRestService.java index f685494d47e..fdbb6d2b27b 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/ExtensionSchemaRestService.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/ExtensionSchemaRestService.java @@ -7,6 +7,7 @@ package com.evolveum.midpoint.model.impl; +import com.evolveum.midpoint.common.configuration.api.MidpointConfiguration; import com.evolveum.midpoint.model.api.ModelAuthorizationAction; import com.evolveum.midpoint.model.impl.security.SecurityHelper; import com.evolveum.midpoint.model.impl.util.RestServiceUtil; @@ -44,8 +45,6 @@ public class ExtensionSchemaRestService { private static final Trace LOGGER = TraceManager.getTrace(ExtensionSchemaRestService.class); - private static final String MIDPOINT_HOME = System.getProperty("midpoint.home"); - @Autowired private PrismContext prismContext; @Autowired private SecurityEnforcer securityEnforcer; @Autowired private SecurityHelper securityHelper; @@ -100,7 +99,8 @@ private String computeName(SchemaDescription description) { return null; } - File home = new File(ExtensionSchemaRestService.MIDPOINT_HOME, "/schema"); + String midpointHome = System.getProperty(MidpointConfiguration.MIDPOINT_HOME_PROPERTY); + File home = new File(midpointHome, "/schema"); java.nio.file.Path homePath = home.toPath(); java.nio.file.Path filePath = file.toPath(); java.nio.file.Path relative = homePath.relativize(filePath); diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/controller/ModelDiagController.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/controller/ModelDiagController.java index bf9f1c0bdaa..f3d2bf1bbac 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/controller/ModelDiagController.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/controller/ModelDiagController.java @@ -24,9 +24,9 @@ import com.evolveum.midpoint.security.enforcer.api.SecurityEnforcer; import com.evolveum.midpoint.util.SystemUtil; import com.evolveum.midpoint.util.exception.*; -import com.evolveum.midpoint.util.template.TemplateEngine; import com.evolveum.midpoint.xml.ns._public.common.common_3.*; import org.apache.commons.io.IOUtils; +import org.apache.commons.text.StringSubstitutor; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Component; @@ -660,7 +660,7 @@ private File getLogFile(OperationResult result) throws SchemaException { .filter(a -> rootLoggerAppender.equals(a.getName())).findFirst().orElse(null); if (rootFileAppender instanceof FileAppenderConfigurationType) { String fileName = ((FileAppenderConfigurationType) rootFileAppender).getFileName(); - return new File(TemplateEngine.simpleExpandProperties(fileName)); + return new File(StringSubstitutor.replaceSystemProperties(fileName)); } } } diff --git a/model/report-impl/src/main/java/com/evolveum/midpoint/report/impl/ReportJasperCreateTaskHandler.java b/model/report-impl/src/main/java/com/evolveum/midpoint/report/impl/ReportJasperCreateTaskHandler.java index 49de0b09422..7fd75bede05 100644 --- a/model/report-impl/src/main/java/com/evolveum/midpoint/report/impl/ReportJasperCreateTaskHandler.java +++ b/model/report-impl/src/main/java/com/evolveum/midpoint/report/impl/ReportJasperCreateTaskHandler.java @@ -20,6 +20,7 @@ import javax.annotation.PostConstruct; +import com.evolveum.midpoint.common.configuration.api.MidpointConfiguration; import com.evolveum.midpoint.prism.delta.DeltaFactory; import com.evolveum.midpoint.repo.common.ObjectResolver; import com.evolveum.midpoint.repo.common.commandline.CommandLineScriptExecutor; @@ -53,7 +54,6 @@ import net.sf.jasperreports.export.SimpleOutputStreamExporterOutput; import net.sf.jasperreports.export.SimpleWriterExporterOutput; -import org.apache.commons.codec.binary.Base64; import org.apache.commons.io.FilenameUtils; import org.apache.commons.lang.StringUtils; import org.springframework.beans.factory.annotation.Autowired; @@ -112,10 +112,6 @@ public class ReportJasperCreateTaskHandler implements TaskHandler { // public static final String PARAMETER_TASK = "midpointTask"; // public static final String PARAMETER_OPERATION_RESULT = "midpointOperationResult"; - private static final String MIDPOINT_HOME = System.getProperty("midpoint.home"); - private static final String EXPORT_DIR = MIDPOINT_HOME + "export/"; - private static final String TEMP_DIR = MIDPOINT_HOME + "tmp/"; - private static final String JASPER_VIRTUALIZER_PKG = "net.sf.jasperreports.engine.fill"; @Autowired private TaskManager taskManager; @@ -133,6 +129,18 @@ protected void initialize() { taskManager.registerHandler(REPORT_CREATE_TASK_URI, this); } + private File getExportDir() { + return new File(getMidPointHomeDirName(), "export"); + } + + private String getTempDirName() { + return new File(getMidPointHomeDirName(), "tmp/").getPath(); + } + + private String getMidPointHomeDirName() { + return System.getProperty(MidpointConfiguration.MIDPOINT_HOME_PROPERTY); + } + @Override public TaskRunResult run(RunningTask task, TaskPartitionDefinitionType partition) { OperationResult parentResult = task.getResult(); @@ -215,12 +223,12 @@ public TaskRunResult run(RunningTask task, TaskPartitionDefinitionType partition Class clazz = Class.forName(virtualizerClassName); if (clazz.equals(JRSwapFileVirtualizer.class)) { - swapFile = new JRSwapFile(TEMP_DIR, 4096, 200); + swapFile = new JRSwapFile(getTempDirName(), 4096, 200); virtualizer = new JRSwapFileVirtualizer(virtualizerKickOn, swapFile); } else if (clazz.equals(JRGzipVirtualizer.class)) { virtualizer = new JRGzipVirtualizer(virtualizerKickOn); } else if (clazz.equals(JRFileVirtualizer.class)) { - virtualizer = new JRFileVirtualizer(virtualizerKickOn, TEMP_DIR); + virtualizer = new JRFileVirtualizer(virtualizerKickOn, getTempDirName()); } else { throw new ClassNotFoundException("No support for virtualizer class: " + clazz.getName()); } @@ -535,19 +543,22 @@ public static String getDateTime() { } protected String getDestinationFileName(ReportType reportType) { - File exportFolder = new File(EXPORT_DIR); - if (!exportFolder.exists() || !exportFolder.isDirectory()) { - exportFolder.mkdir(); + File exportDir = getExportDir(); + if (!exportDir.exists() || !exportDir.isDirectory()) { + if (!exportDir.mkdir()) { + LOGGER.error("Couldn't create export dir {}", exportDir); + } } - String output = EXPORT_DIR + reportType.getName().getOrig() + " " + getDateTime(); - + String fileNamePrefix = reportType.getName().getOrig() + " " + getDateTime(); + String fileName; ExportType export = getExport(reportType); if (export == ExportType.XML_EMBED) { - return output + "_embed.xml"; + fileName = fileNamePrefix + "_embed.xml"; + } else { + fileName = fileNamePrefix + "." + export.value(); } - - return output + "." + export.value(); + return new File(getExportDir(), fileName).getPath(); } protected void saveReportOutputType(String filePath, ReportType reportType, Task task, OperationResult parentResult) throws Exception { diff --git a/model/report-impl/src/main/java/com/evolveum/midpoint/report/impl/ReportUtils.java b/model/report-impl/src/main/java/com/evolveum/midpoint/report/impl/ReportUtils.java index f1e3809dae8..0b5986f3c27 100644 --- a/model/report-impl/src/main/java/com/evolveum/midpoint/report/impl/ReportUtils.java +++ b/model/report-impl/src/main/java/com/evolveum/midpoint/report/impl/ReportUtils.java @@ -9,6 +9,7 @@ import com.evolveum.midpoint.audit.api.AuditEventStage; import com.evolveum.midpoint.audit.api.AuditEventType; import com.evolveum.midpoint.certification.api.OutcomeUtils; +import com.evolveum.midpoint.common.configuration.api.MidpointConfiguration; import com.evolveum.midpoint.prism.Containerable; import com.evolveum.midpoint.prism.Item; import com.evolveum.midpoint.prism.PrismContainerValue; @@ -28,7 +29,6 @@ import java.util.HashMap; import java.util.List; import java.util.ResourceBundle; -import java.util.Set; import javax.xml.datatype.XMLGregorianCalendar; import javax.xml.namespace.QName; @@ -84,8 +84,7 @@ */ public class ReportUtils { - private static final String MIDPOINT_HOME = System.getProperty("midpoint.home"); - private static final String EXPORT_DIR = MIDPOINT_HOME + "export/"; + private static final String EXPORT_DIR_NAME = "export/"; private static final Trace LOGGER = TraceManager .getTrace(ReportUtils.class); @@ -191,12 +190,14 @@ public static ExportType getExport(ReportType report) { } public static String getReportOutputFilePath(ReportType reportType) { - File exportFolder = new File(EXPORT_DIR); - if (!exportFolder.exists() || !exportFolder.isDirectory()) { - exportFolder.mkdir(); + File exportDir = getExportDir(); + if (!exportDir.exists() || !exportDir.isDirectory()) { + if (!exportDir.mkdir()) { + LOGGER.error("Couldn't create export dir {}", exportDir); + } } - String output = EXPORT_DIR + reportType.getName().getOrig() + " " + getDateTime(); + String output = new File(exportDir, reportType.getName().getOrig() + " " + getDateTime()).getPath(); switch (reportType.getExport()) { case PDF: @@ -1055,4 +1056,8 @@ public static Map jasperParamsToAuditParams(Map KNOWN_KEYS = Arrays.asList("midpoint.home", KEY_ENABLED); + private static final List KNOWN_KEYS = Arrays.asList(MidpointConfiguration.MIDPOINT_HOME_PROPERTY, KEY_ENABLED); private static final List DEPRECATED_KEYS = Collections.emptyList(); @Autowired diff --git a/repo/repo-sql-impl/pom.xml b/repo/repo-sql-impl/pom.xml index 499728a2570..f97ee50555a 100644 --- a/repo/repo-sql-impl/pom.xml +++ b/repo/repo-sql-impl/pom.xml @@ -135,7 +135,7 @@ commons-beanutils - commons-beanutils-core + commons-beanutils xml-apis diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/SqlAuditServiceFactory.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/SqlAuditServiceFactory.java index 409f1e6bce1..ebd0e731e78 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/SqlAuditServiceFactory.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/SqlAuditServiceFactory.java @@ -62,8 +62,8 @@ public synchronized void init(Configuration config) throws AuditServiceFactoryEx try { repositoryFactory.init(config); auditService = new SqlAuditServiceImpl(repositoryFactory); - List> subConfigColumns = ((BaseHierarchicalConfiguration)config).childConfigurationsAt(CONF_AUDIT_SERVICE_COLUMNS); - for(Configuration subConfigColumn : subConfigColumns) { + List> subConfigColumns = ((BaseHierarchicalConfiguration)config).configurationsAt(CONF_AUDIT_SERVICE_COLUMNS); + for (Configuration subConfigColumn : subConfigColumns) { String columnName = getStringFromConfig(subConfigColumn, CONF_AUDIT_SERVICE_COLUMN_NAME); String eventRecordPropertyName = getStringFromConfig(subConfigColumn, CONF_AUDIT_SERVICE_EVENT_RECORD_PROPERTY_NAME); auditService.getCustomColumn().put(eventRecordPropertyName, columnName); diff --git a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/SqlRepositoryConfiguration.java b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/SqlRepositoryConfiguration.java index 7dfc80046f1..3b49935b163 100644 --- a/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/SqlRepositoryConfiguration.java +++ b/repo/repo-sql-impl/src/main/java/com/evolveum/midpoint/repo/sql/SqlRepositoryConfiguration.java @@ -7,6 +7,7 @@ package com.evolveum.midpoint.repo.sql; +import com.evolveum.midpoint.common.configuration.api.MidpointConfiguration; import com.evolveum.midpoint.repo.api.RepositoryServiceFactoryException; import com.evolveum.midpoint.repo.sql.helpers.OrgClosureManager; import com.evolveum.midpoint.repo.sql.perf.SqlPerformanceMonitorImpl; @@ -254,9 +255,6 @@ public static IncompatibleSchemaAction fromValue(String text) { private static final int DEFAULT_MAX_POOL_SIZE = 20; private static final int DEFAULT_MAX_OBJECTS_FOR_IMPLICIT_FETCH_ALL_ITERATION_METHOD = 500; - private static final String USER_HOME_VARIABLE = "user.home"; - private static final String MIDPOINT_HOME_VARIABLE = "midpoint.home"; - public static final String PROPERTY_DATABASE = "database"; public static final String PROPERTY_BASE_DIR = "baseDir"; public static final String PROPERTY_DROP_IF_EXISTS = "dropIfExists"; @@ -552,15 +550,16 @@ private String getDefaultEmbeddedJdbcUrl() { private String getDerivedBaseDir() { LOGGER.debug("Base dir path in configuration was not defined."); String rv; - if (StringUtils.isNotEmpty(System.getProperty(MIDPOINT_HOME_VARIABLE))) { - rv = System.getProperty(MIDPOINT_HOME_VARIABLE); - LOGGER.info("Using {} with value {} as base dir for configuration.", MIDPOINT_HOME_VARIABLE, rv); - } else if (StringUtils.isNotEmpty(System.getProperty(USER_HOME_VARIABLE))) { - rv = System.getProperty(USER_HOME_VARIABLE); - LOGGER.info("Using {} with value {} as base dir for configuration.", USER_HOME_VARIABLE, rv); + if (StringUtils.isNotEmpty(System.getProperty(MidpointConfiguration.MIDPOINT_HOME_PROPERTY))) { + rv = System.getProperty(MidpointConfiguration.MIDPOINT_HOME_PROPERTY); + LOGGER.info("Using {} with value {} as base dir for configuration.", MidpointConfiguration.MIDPOINT_HOME_PROPERTY, rv); + } else if (StringUtils.isNotEmpty(System.getProperty(MidpointConfiguration.USER_HOME_PROPERTY))) { + rv = System.getProperty(MidpointConfiguration.USER_HOME_PROPERTY); + LOGGER.info("Using {} with value {} as base dir for configuration.", MidpointConfiguration.USER_HOME_PROPERTY, rv); } else { rv = "."; - LOGGER.info("Using '.' as base dir for configuration (neither {} nor {} was defined).", MIDPOINT_HOME_VARIABLE, USER_HOME_VARIABLE); + LOGGER.info("Using '.' as base dir for configuration (neither {} nor {} was defined).", + MidpointConfiguration.MIDPOINT_HOME_PROPERTY, MidpointConfiguration.USER_HOME_PROPERTY); } return rv; } diff --git a/repo/system-init/src/main/java/com/evolveum/midpoint/init/ApplicationHomeSetup.java b/repo/system-init/src/main/java/com/evolveum/midpoint/init/ApplicationHomeSetup.java index a4eedbb12b4..e72f540a0ef 100644 --- a/repo/system-init/src/main/java/com/evolveum/midpoint/init/ApplicationHomeSetup.java +++ b/repo/system-init/src/main/java/com/evolveum/midpoint/init/ApplicationHomeSetup.java @@ -17,25 +17,26 @@ import java.net.URISyntaxException; import static com.evolveum.midpoint.common.configuration.api.MidpointConfiguration.MIDPOINT_HOME_PROPERTY; -import static com.evolveum.midpoint.common.configuration.api.MidpointConfiguration.MIDPOINT_SILENT_PROPERTY; -public class ApplicationHomeSetup { +class ApplicationHomeSetup { private static final Trace LOGGER = TraceManager.getTrace(ApplicationHomeSetup.class); - private boolean silent = false; + private final boolean silent; + private final String midPointHomePath; - public void init() { - this.silent = Boolean.getBoolean(MIDPOINT_SILENT_PROPERTY); - - String midpointHomePath = System.getProperty(MIDPOINT_HOME_PROPERTY); + ApplicationHomeSetup(boolean silent, String midPointHomePath) { + this.silent = silent; + this.midPointHomePath = midPointHomePath; + } - String homeMessage = MIDPOINT_HOME_PROPERTY + " = " + midpointHomePath; - LOGGER.info(homeMessage); + void init() { + String homeMessage = MIDPOINT_HOME_PROPERTY + " = " + midPointHomePath; + LOGGER.info("{}", homeMessage); printToSysout(homeMessage); - createMidpointHomeDirectories(midpointHomePath); - setupMidpointHomeDirectory(midpointHomePath); + createMidpointHomeDirectories(); + setupMidpointHomeDirectory(); } private void printToSysout(String message) { @@ -49,24 +50,21 @@ private void printToSysout(String message) { *

    * Directory information based on: http://wiki.evolveum.com/display/midPoint/midpoint.home+-+directory+structure */ - private void createMidpointHomeDirectories(String midpointHomePath) { - if (!checkDirectoryExistence(midpointHomePath)) { - createDir(midpointHomePath); + private void createMidpointHomeDirectories() { + if (!checkDirectoryExistence(midPointHomePath)) { + createDir(midPointHomePath); } - if (!midpointHomePath.endsWith("/")) { - midpointHomePath = midpointHomePath + "/"; - } String[] directories = { - midpointHomePath + "icf-connectors", - midpointHomePath + "idm-legacy", - midpointHomePath + "log", - midpointHomePath + "schema", - midpointHomePath + "import", - midpointHomePath + "export", - midpointHomePath + "tmp", - midpointHomePath + "lib", - midpointHomePath + "trace" + midPointHomePath + "icf-connectors", + midPointHomePath + "idm-legacy", + midPointHomePath + "log", + midPointHomePath + "schema", + midPointHomePath + "import", + midPointHomePath + "export", + midPointHomePath + "tmp", + midPointHomePath + "lib", + midPointHomePath + "trace" }; for (String directory : directories) { @@ -78,13 +76,12 @@ private void createMidpointHomeDirectories(String midpointHomePath) { } } - private void setupMidpointHomeDirectory(String midpointHomePath) { + private void setupMidpointHomeDirectory() { try { - ClassPathUtil.extractFilesFromClassPath("initial-midpoint-home", midpointHomePath, false); + ClassPathUtil.extractFilesFromClassPath("initial-midpoint-home", midPointHomePath, false); } catch (URISyntaxException | IOException e) { - LOGGER.error("Error copying the content of initial-midpoint-home to {}: {}", midpointHomePath, e.getMessage(), e); + LOGGER.error("Error copying the content of initial-midpoint-home to {}: {}", midPointHomePath, e.getMessage(), e); } - } private boolean checkDirectoryExistence(String dir) { diff --git a/repo/system-init/src/main/java/com/evolveum/midpoint/init/AuditFactory.java b/repo/system-init/src/main/java/com/evolveum/midpoint/init/AuditFactory.java index fc26538c3f2..ae9f86a45f0 100644 --- a/repo/system-init/src/main/java/com/evolveum/midpoint/init/AuditFactory.java +++ b/repo/system-init/src/main/java/com/evolveum/midpoint/init/AuditFactory.java @@ -18,6 +18,7 @@ import org.apache.commons.configuration2.*; import org.apache.commons.configuration2.tree.ImmutableNode; import org.apache.commons.lang.StringUtils; +import org.jetbrains.annotations.NotNull; import org.springframework.beans.BeansException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; @@ -43,10 +44,11 @@ public class AuditFactory implements ApplicationContextAware, RuntimeConfigurati public void init() { Configuration config = getCurrentConfiguration(); List> auditServices = - ((BaseHierarchicalConfiguration) config).childConfigurationsAt(CONF_AUDIT_SERVICE); + ((BaseHierarchicalConfiguration) config).configurationsAt(CONF_AUDIT_SERVICE); for (Configuration serviceConfig : auditServices) { try { String factoryClass = getFactoryClassName(serviceConfig); + //noinspection unchecked Class clazz = (Class) Class.forName(factoryClass); AuditServiceFactory factory = getFactory(clazz); factory.init(serviceConfig); @@ -107,7 +109,7 @@ public AuditService getAuditService() { } @Override - public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + public void setApplicationContext(@NotNull ApplicationContext applicationContext) throws BeansException { this.applicationContext = applicationContext; } diff --git a/repo/system-init/src/main/java/com/evolveum/midpoint/init/ConfigurableProtectorFactory.java b/repo/system-init/src/main/java/com/evolveum/midpoint/init/ConfigurableProtectorFactory.java index ea95ade8a37..ca6ea87f514 100644 --- a/repo/system-init/src/main/java/com/evolveum/midpoint/init/ConfigurableProtectorFactory.java +++ b/repo/system-init/src/main/java/com/evolveum/midpoint/init/ConfigurableProtectorFactory.java @@ -38,11 +38,6 @@ public void init() { Configuration config = configuration.getConfiguration(MidpointConfiguration.PROTECTOR_CONFIGURATION); protectorConfig = new ProtectorConfiguration(config); - //Extract file if not exists - if (config.getString("midpoint.home") == null) { - return; - } - String keyStorePath = protectorConfig.getKeyStorePath(); if (keyStorePath == null) { throw new SystemException("Keystore path not defined"); diff --git a/repo/system-init/src/main/java/com/evolveum/midpoint/init/StartupConfiguration.java b/repo/system-init/src/main/java/com/evolveum/midpoint/init/StartupConfiguration.java index a3286cde0b3..e377010bbe6 100644 --- a/repo/system-init/src/main/java/com/evolveum/midpoint/init/StartupConfiguration.java +++ b/repo/system-init/src/main/java/com/evolveum/midpoint/init/StartupConfiguration.java @@ -12,38 +12,35 @@ import com.evolveum.midpoint.common.configuration.api.MidpointConfiguration; import com.evolveum.midpoint.common.configuration.api.ProfilingMode; import com.evolveum.midpoint.common.configuration.api.SystemConfigurationSection; +import com.evolveum.midpoint.init.interpol.HostnameLookup; +import com.evolveum.midpoint.init.interpol.RandomLookup; import com.evolveum.midpoint.util.ClassPathUtil; -import com.evolveum.midpoint.util.DOMUtil; import com.evolveum.midpoint.util.QNameUtil; import com.evolveum.midpoint.util.SystemUtil; import com.evolveum.midpoint.util.exception.SystemException; import com.evolveum.midpoint.util.logging.LoggingUtils; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; -import org.apache.commons.configuration2.CompositeConfiguration; import org.apache.commons.configuration2.Configuration; import org.apache.commons.configuration2.XMLConfiguration; import org.apache.commons.configuration2.builder.FileBasedConfigurationBuilder; import org.apache.commons.configuration2.builder.fluent.Parameters; import org.apache.commons.configuration2.ex.ConfigurationException; +import org.apache.commons.configuration2.interpol.ConfigurationInterpolator; +import org.apache.commons.configuration2.interpol.Lookup; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; -import org.apache.commons.lang3.Validate; import org.apache.wss4j.dom.engine.WSSConfig; import org.jetbrains.annotations.NotNull; import org.slf4j.LoggerFactory; -import javax.xml.parsers.DocumentBuilder; import java.io.File; import java.io.FileReader; import java.io.IOException; -import java.util.Iterator; -import java.util.List; -import java.util.Properties; +import java.util.*; public class StartupConfiguration implements MidpointConfiguration { - private static final String USER_HOME_SYSTEM_PROPERTY_NAME = "user.home"; private static final String SAFE_MODE = "safeMode"; private static final String PROFILING_ENABLED = "profilingEnabled"; private static final String PROFILING_MODE = "profilingMode"; @@ -58,10 +55,9 @@ public class StartupConfiguration implements MidpointConfiguration { private boolean silent = false; - // TODO why CompositeConfiguration here? - private CompositeConfiguration config = null; - private String midPointHomePath = null; - private String configFilename; + private XMLConfiguration config; + private String midPointHomePath; + private final String configFilename; /** * Default constructor @@ -84,7 +80,7 @@ public StartupConfiguration(String midPointHome, String configFilename) { */ @SuppressWarnings("WeakerAccess") public String getConfigFilename() { - return this.configFilename; + return configFilename; } @Override @@ -93,44 +89,25 @@ public String getMidpointHome() { } @Override - public Configuration getConfiguration(String componentName) { - Validate.notNull(componentName, "componentName"); - + public Configuration getConfiguration(@NotNull String componentName) { Configuration sub = config.subset(componentName); - applyMidpointHome(sub); dumpConfiguration(componentName, sub); return sub; } @Override public Configuration getConfiguration() { - applyMidpointHome(config); dumpConfiguration("", config); return config; } - // TODO rewrite the following midpoint.home magic - private void applyMidpointHome(Configuration sub) { - // Insert replacement for relative path to midpoint.home else clean replace - if (getMidpointHome() != null) { - sub.addProperty(MIDPOINT_HOME_PROPERTY, getMidpointHome()); - } else { - Iterator i = sub.getKeys(); - while (i.hasNext()) { - String key = i.next(); - sub.setProperty(key, sub.getString(key).replace("${" + MIDPOINT_HOME_PROPERTY + "}/", "")); - sub.setProperty(key, sub.getString(key).replace("${" + MIDPOINT_HOME_PROPERTY + "}", "")); - } - } - } - private void dumpConfiguration(String componentName, Configuration sub) { if (LOGGER.isDebugEnabled()) { - LOGGER.debug("Configuration for {} :", componentName); + LOGGER.debug("Configuration for {}:", componentName); Iterator i = sub.getKeys(); while (i.hasNext()) { String key = i.next(); - LOGGER.debug(" {} = {}", key, sub.getProperty(key)); + LOGGER.debug(" {} = {}", key, sub.getString(key)); } } } @@ -139,15 +116,13 @@ private void dumpConfiguration(String componentName, Configuration sub) { * Initialize system configuration */ public void init() { - this.silent = Boolean.getBoolean(MIDPOINT_SILENT_PROPERTY); + silent = Boolean.getBoolean(MIDPOINT_SILENT_PROPERTY); + midPointHomePath = determineMidpointHome(); - initializeMidpointHomePath(); + setupInitialLoggingFromHomeDirectory(); + new ApplicationHomeSetup(silent, midPointHomePath).init(); - File midpointHome = new File(midPointHomePath); - - setupInitialLoggingFromHomeDirectory(midpointHome); - - loadConfiguration(midpointHome); + loadConfiguration(); if (isSafeMode()) { LOGGER.info("Safe mode is ON; setting tolerateUndeclaredPrefixes to TRUE"); @@ -160,57 +135,33 @@ public void init() { WSSConfig.init(); } - private void initializeMidpointHomePath() { - if (midPointHomePath == null) { - if (StringUtils.isEmpty(System.getProperty(MIDPOINT_HOME_PROPERTY))) { - midPointHomePath = System.getProperty(USER_HOME_SYSTEM_PROPERTY_NAME); - if (!midPointHomePath.endsWith("/")) { - midPointHomePath += "/"; - } - midPointHomePath += "midpoint"; - LOGGER.info("{} system property is not set, using default value of {}", MIDPOINT_HOME_PROPERTY, midPointHomePath); - } else { - midPointHomePath = System.getProperty(MIDPOINT_HOME_PROPERTY); - } - } - - if (midPointHomePath != null) { - if (!midPointHomePath.endsWith("/")) { - midPointHomePath = midPointHomePath + "/"; - } + private String determineMidpointHome() { + String midPointHome; + String midPointHomeProperty = System.getProperty(MIDPOINT_HOME_PROPERTY); + if (StringUtils.isNotEmpty(midPointHomeProperty)) { + midPointHome = normalizeDirectoryPath(midPointHomeProperty); + } else { + midPointHome = normalizeDirectoryPath(System.getProperty(USER_HOME_PROPERTY)) + "midpoint"; + LOGGER.info("{} system property is not set, using default value of {}", MIDPOINT_HOME_PROPERTY, midPointHome); } - // This is not really good practice. But some components such as reports rely on well-formatted midpoint.home system property. - System.setProperty(MIDPOINT_HOME_PROPERTY, midPointHomePath); + System.setProperty(MIDPOINT_HOME_PROPERTY, midPointHome); + return midPointHome; } - /** - * Loading logic - */ - private void loadConfiguration(@NotNull File midpointHome) { - if (config != null) { - config.clear(); - } else { - config = new CompositeConfiguration(); -// config.setDelimiterParsingDisabled(true); - } - - DocumentBuilder documentBuilder = DOMUtil.createDocumentBuilder(); // we need namespace-aware document builder (see GeneralChangeProcessor.java) - - ApplicationHomeSetup ah = new ApplicationHomeSetup(); - ah.init(); + private String normalizeDirectoryPath(String path) { + return path.endsWith("/") ? path : path + "/"; + } - File configFile = new File(midpointHome, this.getConfigFilename()); + private void loadConfiguration() { + File configFile = new File(midPointHomePath, this.getConfigFilename()); printToSysout("Loading midPoint configuration from file " + configFile); LOGGER.info("Loading midPoint configuration from file {}", configFile); try { if (!configFile.exists()) { extractConfigurationFile(configFile); } - - //Load and parse properties - config.addProperty(MIDPOINT_HOME_PROPERTY, midPointHomePath); - createXmlConfiguration(documentBuilder, configFile.getPath()); + createXmlConfiguration(configFile.getPath()); } catch (ConfigurationException e) { String message = "Unable to read configuration file [" + configFile + "]: " + e.getMessage(); LOGGER.error(message); @@ -245,17 +196,23 @@ private void printToSysout(String message) { } } - private void setupInitialLoggingFromHomeDirectory(File midpointHome) { - File logbackConfigFile = new File(midpointHome, LOGBACK_CONFIG_FILENAME); - boolean clear = false; - if (logbackConfigFile.exists()) { + private void setupInitialLoggingFromHomeDirectory() { + File logbackConfigFile; + boolean clear; + + File standardLogbackConfigFile = new File(midPointHomePath, LOGBACK_CONFIG_FILENAME); + File extraLogbackConfigFile = new File(midPointHomePath, LOGBACK_EXTRA_CONFIG_FILENAME); + + if (standardLogbackConfigFile.exists()) { + logbackConfigFile = standardLogbackConfigFile; clear = true; + } else if (extraLogbackConfigFile.exists()) { + logbackConfigFile = extraLogbackConfigFile; + clear = false; } else { - logbackConfigFile = new File(midpointHome, LOGBACK_EXTRA_CONFIG_FILENAME); - if (!logbackConfigFile.exists()) { - return; - } + return; } + LOGGER.info("Loading logging configuration from {} ({})", logbackConfigFile, clear ? "clearing default configuration" : "extending default configuration"); LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory(); @@ -275,25 +232,29 @@ private void setupInitialLoggingFromHomeDirectory(File midpointHome) { StatusPrinter.printInCaseOfErrorsOrWarnings(context); } - private void createXmlConfiguration(DocumentBuilder documentBuilder, String filename) throws ConfigurationException { + private void createXmlConfiguration(String filename) throws ConfigurationException { + Map lookups = new HashMap<>( + ConfigurationInterpolator.getDefaultPrefixLookups()); + lookups.put(RandomLookup.PREFIX, new RandomLookup()); + lookups.put(HostnameLookup.PREFIX, new HostnameLookup()); + FileBasedConfigurationBuilder builder = new FileBasedConfigurationBuilder<>(XMLConfiguration.class) .configure( new Parameters() .xml() .setFileName(filename) - .setDocumentBuilder(documentBuilder) + .setPrefixLookups(lookups) ); - XMLConfiguration xmlConfig = builder.getConfiguration(); - config.addConfiguration(xmlConfig); + config = builder.getConfiguration(); + config.addProperty(MIDPOINT_HOME_PROPERTY, midPointHomePath); applyEnvironmentProperties(); resolveFileReferences(); } private void resolveFileReferences() { String fileIndirectionSuffix = getFileIndirectionSuffix(); - //noinspection unchecked - ((Iterator) config.getKeys()).forEachRemaining(key -> { + config.getKeys().forEachRemaining(key -> { if (key.endsWith(fileIndirectionSuffix)) { String filename = config.getString(key); String valueKey = StringUtils.removeEnd(key, fileIndirectionSuffix); @@ -331,12 +292,7 @@ private void applyEnvironmentProperties() { private void overrideProperty(String key, Object value) { LOGGER.debug("Overriding property {} to '{}'", key, value); - String[] components = key.split("\\."); - Configuration c = config; - for (int i = 0, componentsLength = components.length; i < componentsLength-1; i++) { - c = c.subset(components[i]); - } - c.setProperty(components[components.length-1], value); + config.setProperty(key, value); } @Override @@ -366,6 +322,7 @@ public ProfilingMode getProfilingMode() { } } + @NotNull @Override public SystemConfigurationSection getSystemSection() { return new SystemConfigurationSectionImpl(getConfiguration(SYSTEM_CONFIGURATION)); @@ -386,7 +343,6 @@ private Configuration getRootConfiguration() { @Override public String toString() { - @SuppressWarnings("unchecked") Iterator i = config.getKeys(); StringBuilder sb = new StringBuilder(); while (i.hasNext()) { diff --git a/repo/system-init/src/main/java/com/evolveum/midpoint/init/interpol/HostnameLookup.java b/repo/system-init/src/main/java/com/evolveum/midpoint/init/interpol/HostnameLookup.java new file mode 100644 index 00000000000..62bd868e0aa --- /dev/null +++ b/repo/system-init/src/main/java/com/evolveum/midpoint/init/interpol/HostnameLookup.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2019 Evolveum and contributors + * + * This work is dual-licensed under the Apache License 2.0 + * and European Union Public License. See LICENSE file for details. + */ + +package com.evolveum.midpoint.init.interpol; + +import com.evolveum.midpoint.util.NetworkUtil; +import com.evolveum.midpoint.util.logging.LoggingUtils; +import com.evolveum.midpoint.util.logging.Trace; +import com.evolveum.midpoint.util.logging.TraceManager; +import org.apache.commons.configuration2.interpol.Lookup; + +import java.net.UnknownHostException; + +/** + * TODO consider moving this downwards to make it available for the rest of midPoint (not only to config.xml parsing). + */ +public class HostnameLookup implements Lookup { + + private static final transient Trace LOGGER = TraceManager.getTrace(HostnameLookup.class); + + public static final String PREFIX = "hostname"; + + @Override + public Object lookup(String variable) { + try { + String hostName = NetworkUtil.getLocalHostNameFromOperatingSystem(); + if (hostName == null) { + LOGGER.error("Couldn't get local host name"); + } + return hostName; + } catch (UnknownHostException e) { + LoggingUtils.logUnexpectedException(LOGGER, "Couldn't get local host name", e); + return null; + } + } +} diff --git a/repo/system-init/src/main/java/com/evolveum/midpoint/init/interpol/RandomLookup.java b/repo/system-init/src/main/java/com/evolveum/midpoint/init/interpol/RandomLookup.java new file mode 100644 index 00000000000..c0cd2aa4d75 --- /dev/null +++ b/repo/system-init/src/main/java/com/evolveum/midpoint/init/interpol/RandomLookup.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2019 Evolveum and contributors + * + * This work is dual-licensed under the Apache License 2.0 + * and European Union Public License. See LICENSE file for details. + */ + +package com.evolveum.midpoint.init.interpol; + +import org.apache.commons.configuration2.interpol.Lookup; + +/** + * Variable is in the form + * - (empty) + * - number + * - number:Y or + * - number:X:Y + * + * Returns a random number between X and Y (inclusive), with the default values of X = 0, Y = 999999999. + * + * TODO consider moving this downwards to make it available for the rest of midPoint (not only to config.xml parsing). + */ +public class RandomLookup implements Lookup { + + public static final String PREFIX = "random"; + + @Override + public Object lookup(String variable) { + String[] parts = variable.split(":"); + long lower = 0, upper = 999999999; + if (parts.length == 0) { + // use the defaults + } else if (!"number".equals(parts[0])) { + throw new IllegalArgumentException("Only random numbers are supported yet. Variable = " + PREFIX + ":" + variable); + } else if (parts.length == 2) { + upper = Long.parseLong(parts[1]); + } else if (parts.length == 3) { + lower = Long.parseLong(parts[1]); + upper = Long.parseLong(parts[2]); + } else if (parts.length > 3) { + throw new IllegalArgumentException("Too many parts in " + PREFIX + ":" + variable); + } + return String.valueOf(lower + (long) (Math.random() * (upper+1-lower))); + } +} diff --git a/repo/system-init/src/test/java/com/evolveum/midpoint/init/TestConfigurationLoad.java b/repo/system-init/src/test/java/com/evolveum/midpoint/init/TestConfigurationLoad.java index 5b695e1fc4d..f5d016c3ea1 100644 --- a/repo/system-init/src/test/java/com/evolveum/midpoint/init/TestConfigurationLoad.java +++ b/repo/system-init/src/test/java/com/evolveum/midpoint/init/TestConfigurationLoad.java @@ -31,30 +31,26 @@ public class TestConfigurationLoad { public void test010SimpleConfigTest() { LOGGER.info("---------------- test010SimpleConfigTest -----------------"); - System.clearProperty("midpoint.home"); - LOGGER.info("midpoint.home => " + System.getProperty("midpoint.home")); + System.clearProperty(MidpointConfiguration.MIDPOINT_HOME_PROPERTY); + LOGGER.info("midpoint.home => {}", System.getProperty(MidpointConfiguration.MIDPOINT_HOME_PROPERTY)); - assertNull(System.getProperty("midpoint.home"), "midpoint.home"); + assertNull(System.getProperty(MidpointConfiguration.MIDPOINT_HOME_PROPERTY), "midpoint.home"); StartupConfiguration sc = new StartupConfiguration(); - assertNotNull(sc); sc.init(); Configuration c = sc.getConfiguration(MidpointConfiguration.REPOSITORY_CONFIGURATION); assertEquals(c.getString("repositoryServiceFactoryClass"), "com.evolveum.midpoint.repo.sql.SqlRepositoryFactory"); - LOGGER.info(sc.toString()); + LOGGER.info("{}", sc); - @SuppressWarnings("unchecked") Iterator i = c.getKeys(); - - while ( i.hasNext()) { + while (i.hasNext()) { String key = i.next(); LOGGER.info(" " + key + " = " + c.getString(key)); } assertEquals(c.getBoolean("asServer"), true); - assertEquals(c.getString("baseDir"), System.getProperty("midpoint.home") ); - + assertEquals(c.getString("baseDir"), System.getProperty(MidpointConfiguration.MIDPOINT_HOME_PROPERTY)); } /** @@ -65,9 +61,8 @@ public void test020DirectoryAndExtractionTest() throws Exception { LOGGER.info("---------------- test020DirectoryAndExtractionTest -----------------"); File midpointHome = new File("target/midPointHome"); - System.setProperty("midpoint.home", "target/midPointHome/"); + System.setProperty(MidpointConfiguration.MIDPOINT_HOME_PROPERTY, "target/midPointHome/"); StartupConfiguration sc = new StartupConfiguration(); - assertNotNull(sc); sc.init(); assertNotNull(midpointHome); @@ -89,9 +84,6 @@ public void test020DirectoryAndExtractionTest() throws Exception { TestUtil.assertPrivateFilePermissions(keystoreFile); //cleanup - System.clearProperty("midpoint.home"); - + System.clearProperty(MidpointConfiguration.MIDPOINT_HOME_PROPERTY); } - - } diff --git a/repo/task-quartz-impl/pom.xml b/repo/task-quartz-impl/pom.xml index 7fdb14ab072..8c35c8d2e03 100644 --- a/repo/task-quartz-impl/pom.xml +++ b/repo/task-quartz-impl/pom.xml @@ -80,6 +80,10 @@ org.apache.commons commons-configuration2 + + org.apache.commons + commons-text + commons-logging commons-logging diff --git a/repo/task-quartz-impl/src/main/java/com/evolveum/midpoint/task/quartzimpl/NodeIdComputer.java b/repo/task-quartz-impl/src/main/java/com/evolveum/midpoint/task/quartzimpl/NodeIdComputer.java index df734fd092c..2ff6210d36a 100644 --- a/repo/task-quartz-impl/src/main/java/com/evolveum/midpoint/task/quartzimpl/NodeIdComputer.java +++ b/repo/task-quartz-impl/src/main/java/com/evolveum/midpoint/task/quartzimpl/NodeIdComputer.java @@ -15,7 +15,6 @@ import com.evolveum.midpoint.schema.SearchResultList; import com.evolveum.midpoint.schema.result.OperationResult; import com.evolveum.midpoint.task.api.TaskManagerConfigurationException; -import com.evolveum.midpoint.task.quartzimpl.cluster.NodeRegistrar; import com.evolveum.midpoint.util.exception.ObjectAlreadyExistsException; import com.evolveum.midpoint.util.exception.ObjectNotFoundException; import com.evolveum.midpoint.util.exception.SchemaException; @@ -23,16 +22,12 @@ import com.evolveum.midpoint.util.logging.LoggingUtils; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; -import com.evolveum.midpoint.util.template.*; import com.evolveum.midpoint.xml.ns._public.common.common_3.NodeType; import org.apache.commons.configuration2.Configuration; +import org.apache.commons.configuration2.interpol.ConfigurationInterpolator; +import org.apache.commons.configuration2.interpol.InterpolatorSpecification; +import org.apache.commons.configuration2.interpol.Lookup; import org.apache.commons.lang3.StringUtils; -import org.jetbrains.annotations.NotNull; - -import java.net.UnknownHostException; -import java.util.Collection; -import java.util.Collections; -import java.util.List; /** * Determines node ID for the current node based on configuration and currently registered nodes. @@ -41,14 +36,13 @@ class NodeIdComputer { private static final transient Trace LOGGER = TraceManager.getTrace(NodeIdComputer.class); - private static final double DEFAULT_RANDOM_RANGE = 1000000000.0; private static final String DEFAULT_NODE_ID = "DefaultNode"; - private static final String NODE_ID_SOURCE_RANDOM = "random"; - private static final String NODE_ID_SOURCE_HOSTNAME = "hostname"; - private static final String NODE_ID_EXPRESSION_SEQUENCE = "sequence"; + private static final int DEFAULT_SEQUENCE_START = 0; + private static final int DEFAULT_SEQUENCE_END = 100; + private static final String DEFAULT_SEQUENCE_FORMAT = "%d"; - private static final int MAX_ITERATIONS = 100; + private static final int MAX_ATTEMPTS_SAFEGUARD = 10000; private final PrismContext prismContext; private final RepositoryService repositoryService; @@ -58,107 +52,105 @@ class NodeIdComputer { this.repositoryService = repositoryService; } - String determineNodeId(Configuration c, boolean clustered, OperationResult result) throws TaskManagerConfigurationException { - String id = c.getString(MidpointConfiguration.MIDPOINT_NODE_ID_PROPERTY, null); - if (StringUtils.isNotEmpty(id)) { - LOGGER.info("Using explicitly provided node ID of '{}'", id); - return id; - } - - String expression = c.getString(MidpointConfiguration.MIDPOINT_NODE_ID_EXPRESSION_PROPERTY, null); - if (StringUtils.isNotEmpty(expression)) { - String idFromExpression = getNodeIdFromExpression(expression, result); - if (StringUtils.isNotEmpty(idFromExpression)) { - LOGGER.info("Using node ID of '{}' as provided by the expression '{}'", idFromExpression, expression); - return idFromExpression; + String determineNodeId(Configuration root, boolean clustered, OperationResult result) throws TaskManagerConfigurationException { + String nodeIdExpression; + Object nodeIdRaw = root.getProperty(MidpointConfiguration.MIDPOINT_NODE_ID_PROPERTY); // this is a value without interpolation + if (nodeIdRaw instanceof String && !"".equals(nodeIdRaw)) { + nodeIdExpression = (String) nodeIdRaw; + } else { + // No nodeId. Let's try nodeIdSource and convert it into nodeId expression. + String source = root.getString(MidpointConfiguration.MIDPOINT_NODE_ID_SOURCE_PROPERTY, null); + if (StringUtils.isNotEmpty(source)) { + nodeIdExpression = "${" + source + (source.contains(":") ? "" : ":") + "}"; } else { - LOGGER.warn("Node ID expression '{}' returned no value, continuing with other options", expression); + nodeIdExpression = null; } } - String source = c.getString(MidpointConfiguration.MIDPOINT_NODE_ID_SOURCE_PROPERTY, null); - if (StringUtils.isNotEmpty(source)) { - String idFromSource = getNodeIdFromSource(source); - if (StringUtils.isNotEmpty(idFromSource)) { - LOGGER.info("Using node ID of '{}' as determined by the '{}' source", idFromSource, source); - return idFromSource; + String nodeId = getNodeIdFromExpression(root.getInterpolator(), nodeIdExpression, result); + if (StringUtils.isNotEmpty(nodeId)) { + if (nodeId.equals(nodeIdExpression)) { + LOGGER.info("Using configured node ID '{}'", nodeId); } else { - LOGGER.warn("Node ID source '{}' provided no value, continuing with other options", source); + LOGGER.info("Using node ID '{}' as provided by '{}' expression", nodeId, nodeIdExpression); } - } - - if (!clustered) { - LOGGER.info("Using default node ID of '{}'", DEFAULT_NODE_ID); + return nodeId; + } else if (!clustered) { + LOGGER.info("Using default node ID '{}'", DEFAULT_NODE_ID); return DEFAULT_NODE_ID; } else { throw new TaskManagerConfigurationException("Node ID must be set when running in clustered mode"); } } - private class BuiltinResolver extends AbstractChainedResolver { + /** + * Expects variable names of start:end:format with the defaults of start=0, end=100, format=%d. + */ + private static class SequenceLookup implements Lookup { - private boolean iterationRequired = false; - private int iterationCounter = 0; + private boolean iterationRequired; + private int iterationCounter; - private BuiltinResolver(ReferenceResolver upstreamResolver, boolean actsAsDefault) { - super(upstreamResolver, actsAsDefault); - } + private int end; + private int number; @Override - protected String resolveLocally(String reference, List parameters) { - if (NODE_ID_SOURCE_RANDOM.equals(reference)) { - double range; - if (parameters.isEmpty()) { - range = DEFAULT_RANDOM_RANGE; - } else if (parameters.size() == 1) { - range = Double.parseDouble(parameters.get(0)); - } else { - throw new IllegalArgumentException("Too many parameters for 'random' expression: " + parameters); - } - return getNodeIdAsRandomValue(range); - } else if (NODE_ID_SOURCE_HOSTNAME.equals(reference)) { - return getNodeIdAsHostName(); - } else if (NODE_ID_EXPRESSION_SEQUENCE.equals(reference)) { - iterationRequired = true; - int iteration = iterationCounter++; - String format; - int base; - if (parameters.size() >= 1) { - format = parameters.get(0); + public String lookup(String variable) { + LOGGER.trace("Lookup called with {}; iteration counter = {}", variable, iterationCounter); + iterationRequired = true; + + int start = DEFAULT_SEQUENCE_START; + end = DEFAULT_SEQUENCE_END; + String format = DEFAULT_SEQUENCE_FORMAT; + + int firstColon = variable.indexOf(':'); + if (firstColon >= 0) { + start = Integer.parseInt(variable.substring(0, firstColon)); + int secondColon = variable.indexOf(':', firstColon+1); + if (secondColon >= 0) { + end = Integer.parseInt(variable.substring(firstColon+1, secondColon)); + format = variable.substring(secondColon+1); } else { - format = "%d"; + end = Integer.parseInt(variable.substring(firstColon+1)); } - if (parameters.size() >= 2) { - base = Integer.parseInt(parameters.get(1)); - } else { - base = 0; - } - if (parameters.size() >= 3) { - throw new IllegalArgumentException("Too many parameters for 'sequence' expression: " + parameters); - } - return String.format(format, base + iteration); - } else { - return null; + } else if (!variable.isEmpty()) { + start = Integer.parseInt(variable); } + number = start + iterationCounter; + String rv = String.format(format, number); + LOGGER.trace("Lookup exiting with {}; iteration counter = {}", rv, iterationCounter); + return rv; } - @NotNull - @Override - protected Collection getScopes() { - return Collections.singleton(""); + private void advance() { + iterationCounter++; } - } - @NotNull - private String getNodeIdFromExpression(String expression, OperationResult result) { - BuiltinResolver builtinResolver = new BuiltinResolver(null, true); - AbstractChainedResolver propertiesResolver = new JavaPropertiesResolver(builtinResolver, true); - AbstractChainedResolver osEnvironmentResolver = new OsEnvironmentResolver(propertiesResolver, true); - TemplateEngine engine = new TemplateEngine(osEnvironmentResolver, true, true); + private boolean isOutOfNumbers() { + return number > end; + } + } - for (;;) { - String candidateNodeId = engine.expand(expression); - if (builtinResolver.iterationRequired) { + private String getNodeIdFromExpression(ConfigurationInterpolator parentInterpolator, String expression, + OperationResult result) { + SequenceLookup sequenceLookup = new SequenceLookup(); + InterpolatorSpecification sequenceProvidingInterpolatorSpec = new InterpolatorSpecification.Builder() + .withParentInterpolator(parentInterpolator) + .withPrefixLookup("sequence", sequenceLookup) + .create(); + ConfigurationInterpolator interpolator = ConfigurationInterpolator.fromSpecification(sequenceProvidingInterpolatorSpec); + for (int attempt = 0; ; attempt++) { + Object interpolationResult = interpolator.interpolate(expression); + if (!(interpolationResult instanceof String)) { + LOGGER.warn("Node ID expression '{}' returned null or non-String value: {}", expression, interpolationResult); + return null; + } + String candidateNodeId = (String) interpolationResult; + if (candidateNodeId.contains("${")) { + // This is a bit of hack: it looks like the node was not resolved correctly. + throw new SystemException("Looks like we couldn't resolve the node ID expression. The (partial) result is: '" + candidateNodeId + "'"); + } + if (sequenceLookup.iterationRequired) { try { // Let us try to create node with given name. If we fail we know we need to iterate. // If we succeed, we will (later) replace the node with the correct content. @@ -185,11 +177,13 @@ private String getNodeIdFromExpression(String expression, OperationResult result } if (existingNodes.isEmpty()) { // Strange. The node should have gone in the meanwhile. To be safe, let's try another one. - LOGGER.info("Node name '{}' seemed to be already reserved. But it cannot be found now. Iterating to the" + LOGGER.warn("Node name '{}' seemed to be already reserved. But it cannot be found now. Iterating to the" + " next one (if possible).", candidateNodeId); + sequenceLookup.advance(); } else if (existingNodes.size() > 1) { LOGGER.warn("Strange: More than one node with the name of '{}': {}. Trying next name in the sequence" + "(if possible).", candidateNodeId, existingNodes); + sequenceLookup.advance(); } else { NodeType existingNode = existingNodes.get(0).asObjectable(); if (Boolean.FALSE.equals(existingNode.isRunning())) { @@ -201,17 +195,21 @@ private String getNodeIdFromExpression(String expression, OperationResult result LoggingUtils.logExceptionAsWarning(LOGGER, "Couldn't delete the node {}. Probably someone" + " else is faster than us.", ex, existingNode); } - builtinResolver.iterationCounter--; // will retry this node + // no advance here } else { - LOGGER.info("Node name '{}' is already reserved. Iterating to next one (if possible).", candidateNodeId); + LOGGER.debug("Node name '{}' is already reserved. Iterating to next one (if possible).", candidateNodeId); + sequenceLookup.advance(); } } - if (builtinResolver.iterationCounter < MAX_ITERATIONS) { - continue; + if (attempt > MAX_ATTEMPTS_SAFEGUARD) { + throw new SystemException("Maximum attempts safeguard value of " + MAX_ATTEMPTS_SAFEGUARD + " has been reached. " + + "Something very strange must have happened."); + } else if (sequenceLookup.isOutOfNumbers()) { + throw new SystemException("Cannot acquire node name. The sequence upper border (" + sequenceLookup.end + + ") has been reached."); } else { - throw new SystemException("Cannot acquire node name. Maximum number of iterations (" - + MAX_ITERATIONS + ") has been reached."); + continue; } } catch (SchemaException e) { throw new SystemException("Unexpected schema exception while creating temporary node: " + e.getMessage(), e); @@ -220,39 +218,4 @@ private String getNodeIdFromExpression(String expression, OperationResult result return candidateNodeId; } } - - @NotNull - private String getNodeIdFromSource(@NotNull String source) { - switch (source) { - case NODE_ID_SOURCE_RANDOM: - return getNodeIdAsRandomValue(DEFAULT_RANDOM_RANGE); - case NODE_ID_SOURCE_HOSTNAME: - return getNodeIdAsHostName(); - default: - throw new IllegalArgumentException("Unsupported node ID source: " + source); - } - } - - @NotNull - private String getNodeIdAsRandomValue(double range) { - return "node-" + Math.round(Math.random() * range); - } - - @NotNull - private String getNodeIdAsHostName() { - try { - String hostName = NodeRegistrar.getLocalHostNameFromOperatingSystem(); - if (hostName != null) { - return hostName; - } else { - LOGGER.error("Couldn't determine nodeId as host name couldn't be obtained from the operating system"); - throw new SystemException( - "Couldn't determine nodeId as host name couldn't be obtained from the operating system"); - } - } catch (UnknownHostException e) { - LoggingUtils.logUnexpectedException(LOGGER, "Couldn't determine nodeId as host name couldn't be obtained from the operating system", e); - throw new SystemException( - "Couldn't determine nodeId as host name couldn't be obtained from the operating system", e); - } - } -} \ No newline at end of file +} diff --git a/repo/task-quartz-impl/src/main/java/com/evolveum/midpoint/task/quartzimpl/TaskManagerConfiguration.java b/repo/task-quartz-impl/src/main/java/com/evolveum/midpoint/task/quartzimpl/TaskManagerConfiguration.java index 6d40164bc65..c8f0b823784 100644 --- a/repo/task-quartz-impl/src/main/java/com/evolveum/midpoint/task/quartzimpl/TaskManagerConfiguration.java +++ b/repo/task-quartz-impl/src/main/java/com/evolveum/midpoint/task/quartzimpl/TaskManagerConfiguration.java @@ -184,7 +184,7 @@ public class TaskManagerConfiguration { private boolean midPointTestMode = false; private static final List KNOWN_KEYS = Arrays.asList( - "midpoint.home", + MidpointConfiguration.MIDPOINT_HOME_PROPERTY, // probably can be removed from this list STOP_ON_INITIALIZATION_FAILURE_CONFIG_ENTRY, THREADS_CONFIG_ENTRY, CLUSTERED_CONFIG_ENTRY, diff --git a/repo/task-quartz-impl/src/main/java/com/evolveum/midpoint/task/quartzimpl/cluster/NodeRegistrar.java b/repo/task-quartz-impl/src/main/java/com/evolveum/midpoint/task/quartzimpl/cluster/NodeRegistrar.java index 7ed74a8c5a6..a7995ae4caa 100644 --- a/repo/task-quartz-impl/src/main/java/com/evolveum/midpoint/task/quartzimpl/cluster/NodeRegistrar.java +++ b/repo/task-quartz-impl/src/main/java/com/evolveum/midpoint/task/quartzimpl/cluster/NodeRegistrar.java @@ -25,6 +25,7 @@ import com.evolveum.midpoint.task.quartzimpl.TaskManagerConfiguration; import com.evolveum.midpoint.task.quartzimpl.TaskManagerQuartzImpl; import com.evolveum.midpoint.util.LocalizableMessageBuilder; +import com.evolveum.midpoint.util.NetworkUtil; import com.evolveum.midpoint.util.exception.ObjectAlreadyExistsException; import com.evolveum.midpoint.util.exception.ObjectNotFoundException; import com.evolveum.midpoint.util.exception.SchemaException; @@ -39,7 +40,6 @@ import org.apache.commons.lang.Validate; import org.apache.commons.lang3.RandomStringUtils; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import javax.management.MBeanServer; import javax.management.ObjectName; @@ -525,7 +525,7 @@ private String getMyHostname() { return taskManager.getConfiguration().getJmxHostName(); } else { try { - String hostName = getLocalHostNameFromOperatingSystem(); + String hostName = NetworkUtil.getLocalHostNameFromOperatingSystem(); if (hostName != null) { return hostName; } else { @@ -600,35 +600,6 @@ private String getMyUrl() { } } - @Nullable - public static String getLocalHostNameFromOperatingSystem() throws UnknownHostException { - // Not entirely correct. But we have no other option here - // other than go native or execute a "hostname" shell command. - // We do not want to do neither. - InetAddress localHost = InetAddress.getLocalHost(); - if (localHost == null) { - String hostname = System.getenv("HOSTNAME"); // Unix - if (StringUtils.isNotEmpty(hostname)) { - return hostname; - } - hostname = System.getenv("COMPUTERNAME"); // Windows - if (StringUtils.isNotEmpty(hostname)) { - return hostname; - } - return null; - } - - String hostname = localHost.getCanonicalHostName(); - if (StringUtils.isNotEmpty(hostname)) { - return hostname; - } - hostname = localHost.getHostName(); - if (StringUtils.isNotEmpty(hostname)) { - return hostname; - } - return localHost.getHostAddress(); - } - private List getMyIpAddresses() { List addresses = new ArrayList<>(); Enumeration nets; diff --git a/repo/task-quartz-impl/src/main/java/com/evolveum/midpoint/task/quartzimpl/handlers/PartitioningTaskHandler.java b/repo/task-quartz-impl/src/main/java/com/evolveum/midpoint/task/quartzimpl/handlers/PartitioningTaskHandler.java index 60000b90e12..8b0d7dacf2b 100644 --- a/repo/task-quartz-impl/src/main/java/com/evolveum/midpoint/task/quartzimpl/handlers/PartitioningTaskHandler.java +++ b/repo/task-quartz-impl/src/main/java/com/evolveum/midpoint/task/quartzimpl/handlers/PartitioningTaskHandler.java @@ -17,7 +17,7 @@ import com.evolveum.midpoint.task.api.TaskPartitionsDefinition.TaskPartitionDefinition; import com.evolveum.midpoint.task.api.TaskRunResult.TaskRunResultStatus; import com.evolveum.midpoint.task.quartzimpl.TaskManagerQuartzImpl; -import com.evolveum.midpoint.util.template.TemplateEngine; +import com.evolveum.midpoint.util.template.StringSubstitutorUtil; import com.evolveum.midpoint.util.exception.ObjectAlreadyExistsException; import com.evolveum.midpoint.util.exception.ObjectNotFoundException; import com.evolveum.midpoint.util.exception.SchemaException; @@ -242,7 +242,7 @@ private String createSubtask(int index, TaskPartitionsDefinition partitionsDefin p -> p.getName(masterTask), ps -> ps.getName(masterTask), "{masterTaskName} ({index})", partition, partitionsDefinition); - String name = TemplateEngine.simpleExpand(nameTemplate, replacements); + String name = StringSubstitutorUtil.simpleExpand(nameTemplate, replacements); subtask.setName(PolyStringType.fromOrig(name)); TaskWorkManagementType workManagement = applyDefaults( @@ -262,7 +262,7 @@ private String createSubtask(int index, TaskPartitionsDefinition partitionsDefin ps -> ps.getHandlerUri(masterTask), null, partition, partitionsDefinition); - String handlerUri = TemplateEngine.simpleExpand(handlerUriTemplate, replacements); + String handlerUri = StringSubstitutorUtil.simpleExpand(handlerUriTemplate, replacements); if (handlerUri == null) { // The default for coordinator-based partitions is to put default handler into workers configuration // - but only if both partition and workers handler URIs are null. This is to be revisited some day. @@ -270,10 +270,11 @@ private String createSubtask(int index, TaskPartitionsDefinition partitionsDefin handlerUri = TaskConstants.WORKERS_CREATION_TASK_HANDLER_URI; if (workManagement.getWorkers() != null && workManagement.getWorkers().getHandlerUri() == null) { workManagement = workManagement.clone(); - workManagement.getWorkers().setHandlerUri(TemplateEngine.simpleExpand(DEFAULT_HANDLER_URI, replacements)); + workManagement.getWorkers().setHandlerUri( + StringSubstitutorUtil.simpleExpand(DEFAULT_HANDLER_URI, replacements)); } } else { - handlerUri = TemplateEngine.simpleExpand(DEFAULT_HANDLER_URI, replacements); + handlerUri = StringSubstitutorUtil.simpleExpand(DEFAULT_HANDLER_URI, replacements); } } subtask.setHandlerUri(handlerUri); diff --git a/repo/task-quartz-impl/src/main/java/com/evolveum/midpoint/task/quartzimpl/tracing/TracerImpl.java b/repo/task-quartz-impl/src/main/java/com/evolveum/midpoint/task/quartzimpl/tracing/TracerImpl.java index 9b165501483..ed5e43b7970 100644 --- a/repo/task-quartz-impl/src/main/java/com/evolveum/midpoint/task/quartzimpl/tracing/TracerImpl.java +++ b/repo/task-quartz-impl/src/main/java/com/evolveum/midpoint/task/quartzimpl/tracing/TracerImpl.java @@ -7,6 +7,7 @@ package com.evolveum.midpoint.task.quartzimpl.tracing; +import com.evolveum.midpoint.common.configuration.api.MidpointConfiguration; import com.evolveum.midpoint.prism.*; import com.evolveum.midpoint.prism.util.CloneUtil; import com.evolveum.midpoint.prism.xml.XmlTypeConverter; @@ -31,6 +32,7 @@ import com.evolveum.midpoint.util.logging.TraceManager; import com.evolveum.midpoint.xml.ns._public.common.common_3.*; import org.apache.commons.lang.StringUtils; +import org.apache.commons.text.StringSubstitutor; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.springframework.beans.factory.annotation.Autowired; @@ -80,8 +82,7 @@ public class TracerImpl implements Tracer, SystemConfigurationChangeListener { private static final String OP_STORE_TRACE = TracerImpl.class.getName() + ".storeTrace"; - private static final String MIDPOINT_HOME = System.getProperty("midpoint.home"); - private static final String TRACE_DIR = MIDPOINT_HOME + "trace/"; + private static final String TRACE_DIR_NAME = "trace"; private static final String ZIP_ENTRY_NAME = "trace.xml"; private static final String DEFAULT_FILE_NAME_PATTERN = "trace-%{timestamp}"; @@ -416,7 +417,7 @@ private String createObjectName(TracingProfileType profile, Map @NotNull private File createFileName(boolean zip, TracingProfileType profile, Map parameters) { - File traceDir = new File(TRACE_DIR); + File traceDir = new File(System.getProperty(MidpointConfiguration.MIDPOINT_HOME_PROPERTY), TRACE_DIR_NAME); if (!traceDir.exists() || !traceDir.isDirectory()) { if (!traceDir.mkdir()) { LOGGER.warn("Attempted to create trace directory but failed: {}", traceDir); @@ -431,28 +432,7 @@ private String normalizeFileName(String name) { } private String expandMacros(String pattern, Map parameters) { - StringBuilder sb = new StringBuilder(); - for (int current = 0;;) { - int i = pattern.indexOf("%{", current); - if (i < 0) { - sb.append(pattern.substring(current)); - return sb.toString(); - } - sb.append(pattern, current, i); - int j = pattern.indexOf("}", i); - if (j < 0) { - LOGGER.warn("Missing '}' in pattern '{}'", pattern); - return sb.toString() + " - error - " + parameters.get(MACRO_RANDOM); - } else { - String macroName = pattern.substring(i+2, j); - String value = parameters.get(macroName); - if (value == null) { - LOGGER.warn("Unknown parameter '{}' in pattern '{}'", macroName, pattern); - } - sb.append(value); - } - current = j+1; - } + return new StringSubstitutor(parameters, "%{", "}").replace(pattern); } @Override diff --git a/repo/task-quartz-impl/src/main/java/com/evolveum/midpoint/task/quartzimpl/work/workers/WorkersManager.java b/repo/task-quartz-impl/src/main/java/com/evolveum/midpoint/task/quartzimpl/work/workers/WorkersManager.java index 857a0af751d..8e44de5550b 100644 --- a/repo/task-quartz-impl/src/main/java/com/evolveum/midpoint/task/quartzimpl/work/workers/WorkersManager.java +++ b/repo/task-quartz-impl/src/main/java/com/evolveum/midpoint/task/quartzimpl/work/workers/WorkersManager.java @@ -21,7 +21,7 @@ import com.evolveum.midpoint.schema.result.OperationResultStatus; import com.evolveum.midpoint.task.api.*; import com.evolveum.midpoint.util.MiscUtil; -import com.evolveum.midpoint.util.template.TemplateEngine; +import com.evolveum.midpoint.util.template.StringSubstitutorUtil; import com.evolveum.midpoint.util.exception.ObjectAlreadyExistsException; import com.evolveum.midpoint.util.exception.ObjectNotFoundException; import com.evolveum.midpoint.util.exception.SchemaException; @@ -382,10 +382,10 @@ private WorkerKey createWorkerKey(String nodeIdentifier, int index, WorkerTasksP nameTemplate = "{coordinatorTaskName} ({node}:{index})"; } - String name = TemplateEngine.simpleExpand(nameTemplate, replacements); + String name = StringSubstitutorUtil.simpleExpand(nameTemplate, replacements); String executionGroupTemplate = defaultIfNull(perNodeConfig.getExecutionGroup(), "{node}"); - String executionGroup = MiscUtil.nullIfEmpty(TemplateEngine.simpleExpand(executionGroupTemplate, replacements)); + String executionGroup = MiscUtil.nullIfEmpty(StringSubstitutorUtil.simpleExpand(executionGroupTemplate, replacements)); return new WorkerKey(executionGroup, name, scavenger); } diff --git a/tools/midpoint-war-layout/src/main/java/com/evolveum/midpoint/tools/layout/MidPointWarLauncher.java b/tools/midpoint-war-layout/src/main/java/com/evolveum/midpoint/tools/layout/MidPointWarLauncher.java index 54311477f97..4e1a8790672 100644 --- a/tools/midpoint-war-layout/src/main/java/com/evolveum/midpoint/tools/layout/MidPointWarLauncher.java +++ b/tools/midpoint-war-layout/src/main/java/com/evolveum/midpoint/tools/layout/MidPointWarLauncher.java @@ -97,7 +97,7 @@ protected List getClassPathArchives() throws Exception { List archives = super.getClassPathArchives(); File midPointHomeLib = getMidPointHomeLib(); - if (midPointHomeLib == null || !midPointHomeLib.exists() || !midPointHomeLib.isDirectory()) { + if (!midPointHomeLib.exists() || !midPointHomeLib.isDirectory()) { return archives; } diff --git a/tools/ninja/src/main/java/com/evolveum/midpoint/ninja/impl/NinjaContext.java b/tools/ninja/src/main/java/com/evolveum/midpoint/ninja/impl/NinjaContext.java index 7d59678d813..d6da82cb298 100644 --- a/tools/ninja/src/main/java/com/evolveum/midpoint/ninja/impl/NinjaContext.java +++ b/tools/ninja/src/main/java/com/evolveum/midpoint/ninja/impl/NinjaContext.java @@ -8,6 +8,7 @@ package com.evolveum.midpoint.ninja.impl; import com.beust.jcommander.JCommander; +import com.evolveum.midpoint.common.configuration.api.MidpointConfiguration; import com.evolveum.midpoint.ninja.opts.BaseOptions; import com.evolveum.midpoint.ninja.opts.ConnectionOptions; import com.evolveum.midpoint.ninja.util.InitializationBeanPostprocessor; @@ -27,9 +28,6 @@ */ public class NinjaContext { - private static final String MIDPOINT_SILENT_PROPERTY_NAME = "midpoint.silent"; - private static final String MIDPOINT_HOME_OPTION = "midpoint.home"; - private static final String REPOSITORY_SERVICE_BEAN = "repositoryService"; private static final String CTX_NINJA = "classpath:ctx-ninja.xml"; @@ -91,7 +89,7 @@ public void setLog(Log log) { private RepositoryService setupRepositoryViaMidPointHome(ConnectionOptions options) { log.info("Initializing repository using midpoint home"); - System.setProperty(MIDPOINT_SILENT_PROPERTY_NAME, "true"); + System.setProperty(MidpointConfiguration.MIDPOINT_SILENT_PROPERTY, "true"); String midpointHome = options.getMidpointHome(); @@ -99,7 +97,7 @@ private RepositoryService setupRepositoryViaMidPointHome(ConnectionOptions optio String jdbcUsername = options.getUsername(); String jdbcPassword = getPassword(options); - System.setProperty(MIDPOINT_HOME_OPTION, midpointHome); + System.setProperty(MidpointConfiguration.MIDPOINT_HOME_PROPERTY, midpointHome); InitializationBeanPostprocessor postprocessor = new InitializationBeanPostprocessor(); postprocessor.setJdbcUrl(jdbcUrl);