blob: c314a4d525c45bef5f792b039dc8e7272590410b [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with this
* work for additional information regarding copyright ownership. The ASF
* licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.apache.knox.gateway.topology.discovery.advanced;
import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.attribute.FileTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import org.apache.commons.io.filefilter.PrefixFileFilter;
import org.apache.commons.lang3.concurrent.BasicThreadFactory;
import org.apache.knox.gateway.config.GatewayConfig;
import org.apache.knox.gateway.i18n.messages.MessagesFactory;
/**
* Monitoring <code>$KNOX_CONF_DIR/auto-discovery-advanced-configuration.properties</code> (if exists) and notifies any
* {@link AdvancedServiceDiscoveryConfigChangeListener} if the file is changed since the last time it was loaded
*
*/
public class AdvancedServiceDiscoveryConfigurationMonitor {
private static final String ADVANCED_CONFIGURATION_FILE_NAME_PREFIX = "auto-discovery-advanced-configuration-";
private static final AdvanceServiceDiscoveryConfigurationMessages LOG = MessagesFactory.get(AdvanceServiceDiscoveryConfigurationMessages.class);
private final List<AdvancedServiceDiscoveryConfigChangeListener> listeners;
private final String gatewayConfigurationDir;
private final long monitoringInterval;
private final Map<Path, FileTime> lastReloadTimes;
public AdvancedServiceDiscoveryConfigurationMonitor(GatewayConfig gatewayConfig) {
this.gatewayConfigurationDir = gatewayConfig.getGatewayConfDir();
this.monitoringInterval = gatewayConfig.getClouderaManagerAdvancedServiceDiscoveryConfigurationMonitoringInterval();
this.listeners = new ArrayList<>();
this.lastReloadTimes = new ConcurrentHashMap<>();
}
public void init() {
monitorAdvancedServiceConfigurations();
setupMonitor();
}
private void setupMonitor() {
if (monitoringInterval > 0) {
final ScheduledExecutorService executorService = newSingleThreadScheduledExecutor(new BasicThreadFactory.Builder().namingPattern("AdvancedServiceDiscoveryConfigurationMonitor-%d").build());
executorService.scheduleAtFixedRate(() -> monitorAdvancedServiceConfigurations(), 0, monitoringInterval, TimeUnit.MILLISECONDS);
LOG.monitorStarted(gatewayConfigurationDir, ADVANCED_CONFIGURATION_FILE_NAME_PREFIX);
} else {
LOG.disableMonitoring();
}
}
public void registerListener(AdvancedServiceDiscoveryConfigChangeListener listener) {
listeners.add(listener);
}
private void monitorAdvancedServiceConfigurations() {
final File[] advancedConfigurationFiles = new File(gatewayConfigurationDir).listFiles((FileFilter) new PrefixFileFilter(ADVANCED_CONFIGURATION_FILE_NAME_PREFIX));
if (advancedConfigurationFiles != null) {
for (File advancedConfigurationFile : advancedConfigurationFiles) {
monitorAdvancedServiceConfiguration(Paths.get(advancedConfigurationFile.getAbsolutePath()));
}
}
}
private void monitorAdvancedServiceConfiguration(Path resourcePath) {
try {
if (Files.exists(resourcePath) && Files.isReadable(resourcePath)) {
FileTime lastModifiedTime = Files.getLastModifiedTime(resourcePath);
FileTime lastReloadTime = lastReloadTimes.get(resourcePath);
if (lastReloadTime == null || lastReloadTime.compareTo(lastModifiedTime) < 0) {
lastReloadTimes.put(resourcePath, lastModifiedTime);
try (InputStream advanceconfigurationFileInputStream = Files.newInputStream(resourcePath)) {
Properties properties = new Properties();
properties.load(advanceconfigurationFileInputStream);
notifyListeners(resourcePath.toString(), properties);
}
}
}
} catch (IOException e) {
LOG.failedToMonitorClouderaManagerAdvancedConfiguration(e.getMessage(), e);
}
}
private void notifyListeners(String path, Properties properties) {
LOG.notifyListeners(path);
listeners.forEach(listener -> listener.onAdvancedServiceDiscoveryConfigurationChange(properties));
}
}