/* * Copyright 2014 Federal Chancellery Austria * MOA-ID has been developed in a cooperation between BRZ, the Federal * Chancellery Austria - ICT staff unit, and Graz University of Technology. * * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by * the European Commission - subsequent versions of the EUPL (the "Licence"); * You may not use this work except in compliance with the Licence. * You may obtain a copy of the Licence at: * http://www.osor.eu/eupl/ * * Unless required by applicable law or agreed to in writing, software * distributed under the Licence is distributed on an "AS IS" basis, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Licence for the specific language governing permissions and * limitations under the Licence. * * This product combines work with different licenses. See the "NOTICE" text * file for details on the various modules and licenses. * The "NOTICE" text file is part of the distribution. Any derivative works * that you distribute must include a readable copy of the "NOTICE" text file. */ package at.gv.egovernment.moa.id.config.webgui.validation; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.ServiceLoader; import java.util.Set; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import at.gv.egiz.eaaf.core.impl.utils.KeyValueUtils; import at.gv.egovernment.moa.id.commons.config.MOAIDConfigurationConstants; import at.gv.egovernment.moa.id.commons.config.persistence.MOAIDConfiguration; import at.gv.egovernment.moa.id.config.webgui.exception.ConfigurationModulValidationException; import at.gv.egovernment.moa.id.config.webgui.exception.ConfigurationValidationException; import at.gv.egovernment.moa.id.config.webgui.validation.modul.IModuleValidator; import at.gv.egovernment.moa.id.config.webgui.validation.task.IDynamicLoadableTaskValidator; /** * @author tlenz * */ public class MOAIDConfigurationValidator { private static final Logger logger = LoggerFactory.getLogger(MOAIDConfigurationValidator.class); private static MOAIDConfiguration dbconfig; private static ServiceLoader moduleLoader = ServiceLoader.load(IModuleValidator.class); private static Map moduleValidator = null; private static ServiceLoader taskLoader = ServiceLoader.load(IDynamicLoadableTaskValidator.class); private Map> data = null; private boolean isDataValidated = false; @Autowired public void setDatabaseConfiguration(MOAIDConfiguration config) { dbconfig = config; } /** * */ public MOAIDConfigurationValidator() { //load modules if (moduleValidator == null ) { moduleValidator = new HashMap(); Iterator moduleLoaderInterator = moduleLoader.iterator(); while (moduleLoaderInterator.hasNext()) { IModuleValidator modul = moduleLoaderInterator.next(); logger.info("Load validation module for key: {}", modul.getKeyPrefix()); moduleValidator.put(modul.getKeyPrefix(), modul); } //load dynamic tasks Iterator taskLoaderInterator = taskLoader.iterator(); while (taskLoaderInterator.hasNext()) { IDynamicLoadableTaskValidator task = taskLoaderInterator.next(); List modulesToInject = task.getModulValidatorPrefix(); for (String el : modulesToInject) { if (moduleValidator.containsKey(el)) { moduleValidator.get(el).addTaskValidator(task); logger.info("Task " + task.getName() + " is injected to module with prefix " + el); } else { logger.warn("Task " + task.getName() + " could NOT injected: No module with prefix " + el); } } } } } /** * Get the internal key/value configuration data set * * @return full configuration block of key/value pairs {Map} sorted by MOA-ID configuration groups or null if preprocessing was done */ public Map> getPreProcessedConfigurationData() { return data; } /** * PreProcess MOA-ID key/value configuration before validation and sort the keys into MOA-ID configuration groups * * @param changed all changed key/value pairs * @param added all added key/value pairs * @param deleted all deleted key/value pairs * @return Number of MOA-ID configuration groups which was found */ public int preProcess(Map changed, Map added, List deleted) { data = new HashMap>(); //classify changed key/value pairs if (changed != null) keyValueClassification(changed.entrySet().iterator(), data); //classify new key/value pairs if (added != null) keyValueClassification(added.entrySet().iterator(), data); return data.size(); } /** * Validate MOA-ID key/value configuration before saving * * @throws ConfigurationValidationException */ public void validate() throws ConfigurationValidationException { logger.trace("Starting MOA-ID configuration validation process ..."); Iterator>> groupInterator = data.entrySet().iterator(); while (groupInterator.hasNext()) { Entry> groupEl = groupInterator.next(); try { if (groupEl.getKey().startsWith(MOAIDConfigurationConstants.PREFIX_MOAID_SERVICES)) { String moduleID = KeyValueUtils.getParentKey(groupEl.getKey()); if (moduleValidator.containsKey(moduleID)) { logger.trace("Starting validation process of keyGroup: " + groupEl.getKey() + " with module: " + moduleValidator.get(moduleID).getName()); Map servicekeys = KeyValueUtils.removePrefixFromKeys(groupEl.getValue(), groupEl.getKey()); //put service prefix to validation Map to check if service already stored servicekeys.put(MOAIDConfigurationConstants.PREFIX_MOAID_SERVICES, groupEl.getKey()); moduleValidator.get(moduleID) .validate(servicekeys); } else logger.info("No ModulValidator for keygroup {} found.", moduleID); } else if (moduleValidator.containsKey(groupEl.getKey())) { logger.trace("Starting validation process of keyGroup: " + groupEl.getKey() + " with module: " + moduleValidator.get(groupEl.getKey()).getName()); moduleValidator.get(groupEl.getKey()) .validate(KeyValueUtils.removePrefixFromKeys(groupEl.getValue(), groupEl.getKey())); } else { logger.info("No ModulValidator for keygroup {} found.", groupEl.getKey()); } } catch (ConfigurationModulValidationException e) { logger.warn("Validation of keyGroup: " + groupEl.getKey() + " FAILED with " + e.getValidationErrors().size() + " errors"); throw e; } } isDataValidated = true; } /** * Post-process the validated configuration to generate storeable key/value pairs * @param deleted * * @return {Map} of key/value pairs which could be stored into configuration */ public Map postProcessing(List deleted) { if (!isDataValidated) logger.warn("Post-Processing non validated key/value pairs!"); Map configToStore = new HashMap(); Iterator>> groupInterator = data.entrySet().iterator(); while (groupInterator.hasNext()) { Entry> groupEl = groupInterator.next(); try { if (groupEl.getKey().startsWith(MOAIDConfigurationConstants.PREFIX_MOAID_SERVICES)) { String moduleID = KeyValueUtils.getParentKey(groupEl.getKey()); if (moduleValidator.containsKey(moduleID)) { logger.trace("Start postProcessing of keyGroup: " + groupEl.getKey() + " with module: " + moduleValidator.get(moduleID).getName()); postProcessing(groupEl, moduleValidator.get(moduleID), configToStore, deleted); } else logger.info("No Module for keygroup {} found.", moduleID); } else if (moduleValidator.containsKey(groupEl.getKey())) { logger.trace("Start postProcessing of keyGroup: " + groupEl.getKey() + " with module: " + moduleValidator.get(groupEl.getKey()).getName()); postProcessing(groupEl, moduleValidator.get(groupEl.getKey()), configToStore, deleted); } else { logger.info("No ModulValidator for keygroup {} found.", groupEl.getKey()); } } catch (Exception e) { logger.error("Post-Processing for keygroup: " + groupEl.getKey() + " FAILED!", e); } } return configToStore; } private void postProcessing(Entry> groupEl, IModuleValidator module, Map configToStore, List deleted ) { //add all key/value pairs from user configuration GUI configToStore.putAll(KeyValueUtils.makeKeysAbsolut( groupEl.getValue(), groupEl.getKey(), MOAIDConfigurationConstants.PREFIX_MOAID)); //add or update key/value pairs from users with module or task specific information List taskDelete = new ArrayList(); Map toBeAdded = module.postProcessing( KeyValueUtils.removePrefixFromKeys(groupEl.getValue(), groupEl.getKey()), taskDelete, dbconfig); if (toBeAdded != null) { toBeAdded = KeyValueUtils.makeKeysAbsolut(toBeAdded, groupEl.getKey(), MOAIDConfigurationConstants.PREFIX_MOAID); for (Entry el : toBeAdded.entrySet()) { if (configToStore.containsKey(el.getKey())) { logger.info("Overwrite key: " + el.getKey() + " userValue:" + configToStore.get(el.getKey()) + " postProcessing: " + toBeAdded.get(el.getKey())); } configToStore.put(el.getKey(), el.getValue()); } } //make delete elements absolute if (!taskDelete.isEmpty()) { Iterator delInterator = taskDelete.iterator(); while (delInterator.hasNext()) { String delKey = delInterator.next(); if (!delKey.startsWith(MOAIDConfigurationConstants.PREFIX_MOAID)) { deleted.add(groupEl.getKey() + KeyValueUtils.KEY_DELIMITER + delKey ); } else { deleted.add(delKey); } } } } private void keyValueClassification(Iterator> config, Map> result) { Set validationModuleKeys = moduleValidator.keySet(); while(config.hasNext()) { Entry el = config.next(); logger.trace("Preprocess configuration element with key: " + el.getKey() + " value: " + el.getValue()); //search configuration module IModuleValidator selectedModul = null; for (String key : validationModuleKeys) { if (el.getKey().startsWith(key)) { selectedModul = moduleValidator.get(key); break; } } //group key/value pair to configuration modules if (selectedModul != null) { String groupkey = null; if (selectedModul.getKeyPrefix().startsWith(MOAIDConfigurationConstants.PREFIX_MOAID_SERVICES)) { String oaIndex = KeyValueUtils.getFirstChildAfterPrefix(el.getKey(), selectedModul.getKeyPrefix()); groupkey = selectedModul.getKeyPrefix() + "." + oaIndex; } else groupkey = selectedModul.getKeyPrefix(); if (!result.containsKey(groupkey)) { result.put(groupkey, new HashMap()); } Map resultElement = result.get(groupkey); logger.trace("Put key/value pair to keyGroup: " + groupkey + "with friendlyName: " + selectedModul.getName()); resultElement.put(el.getKey(), el.getValue()); } else { logger.warn("Configuration Key {} is not part of a loaded MOA-ID configuration validation-module!", el.getKey()); } } } }