/* * 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; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; import org.apache.commons.io.IOUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import at.gv.egiz.components.configuration.api.Configuration; import at.gv.egiz.components.configuration.api.ConfigurationException; import at.gv.egiz.components.configuration.file.PropertiesBasedConfiguration; import at.gv.egiz.components.configuration.meta.api.ConfigurationModul; import at.gv.egiz.components.configuration.meta.api.ConfigurationStorageException; import at.gv.egiz.components.configuration.meta.api.MetadataConfiguration; import at.gv.egiz.components.configuration.meta.api.SchemaEntry; import at.gv.egiz.components.configuration.meta.api.impl.BaseMetadataConfiguration; 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.commons.config.persistence.MOAIDConfigurationImpl; import at.gv.egovernment.moa.id.config.webgui.exception.ConfigurationValidationException; import at.gv.egovernment.moa.id.config.webgui.validation.MOAIDConfigurationValidator; /** * @author tlenz * */ @Service public class MOAIDConfigurationModul implements ConfigurationModul{ private static final String MODULE_NAME = "MOAIDConfigurationModul"; private static MOAIDConfiguration config; private static Configuration meta; private static MetadataConfiguration metadata = null; private List schemaList = new ArrayList(); private static final Logger logger = LoggerFactory.getLogger(MOAIDConfigurationModul.class); static { logger.info("Loading class {}", MOAIDConfigurationModul.class.getName()); try { meta = new PropertiesBasedConfiguration(MOAIDConfigurationModul.class.getResourceAsStream("/gui/meta.properties")); } catch (IOException | ConfigurationException e) { logger.error("Failed to build internal datasets in MOAIDConfiguration modul!"); } } @Autowired public void setDatabaseConfiguration(MOAIDConfiguration dbconfig) { config = dbconfig; } /** * @throws Exception * */ public MOAIDConfigurationModul() throws Exception { loadType("general", "/gui/types/general.json"); loadType("moaidoa", "/gui/types/oa.json"); loadType("moaidvidp", "/gui/types/vidp.json"); loadType("moaidiidp", "/gui/types/iidp.json"); loadType("moaidgateway", "/gui/types/gateway.json"); try { MOAIDWebGUIConfiguration.getInstance(); } catch (at.gv.egovernment.moa.id.config.webgui.exception.ConfigurationException e) { logger.error("MOA-ID WebGUI initialization FAILED! (Reason: {})", e.getMessage()); throw new Exception(e); } } /* (non-Javadoc) * @see at.gv.egiz.components.configuration.meta.api.ConfigurationModul#getSchemas() */ @Override public List getSchemas() { return schemaList; } /* (non-Javadoc) * @see at.gv.egiz.components.configuration.meta.api.ConfigurationModul#getName() */ @Override public String getName() { return MODULE_NAME; } /* (non-Javadoc) * @see at.gv.egiz.components.configuration.meta.api.ConfigurationModul#getPrefix() */ @Override public String getPrefix() { return MOAIDConfigurationConstants.PREFIX_MOAID; } /* (non-Javadoc) * @see at.gv.egiz.components.configuration.meta.api.ConfigurationModul#getConfigurationAccess() */ @Override public Configuration getConfigurationAccess() { return config; } /* (non-Javadoc) * @see at.gv.egiz.components.configuration.meta.api.ConfigurationModul#getMetadataConfiguration() */ @Override public MetadataConfiguration getMetadataConfiguration() { if (metadata == null) { metadata = new BaseMetadataConfiguration(config, meta); } return metadata; } /* (non-Javadoc) * @see at.gv.egiz.components.configuration.meta.api.ConfigurationModul#buildArrayIdentifier(java.lang.String, int, java.util.Map) */ @Override public String buildArrayIdentifier(String arrayId, int refCounter, Map properties) throws ConfigurationException { logger.trace("Search next free list index for key: " + arrayId); if (arrayId.startsWith(MOAIDConfigurationConstants.PREFIX_MOAID_SERVICES)) { String[] allListKeys = config.findConfigurationId(arrayId + ".%." + MOAIDConfigurationConstants.SERVICE_UNIQUEIDENTIFIER); int freeIndex = KeyValueUtils.findNextFreeListCounter(allListKeys, arrayId) + refCounter; logger.debug("Found free listIndex: " + freeIndex + " for serviceKey: " + arrayId); return String.valueOf(freeIndex); } else { logger.warn("Actually, only services are from type array and need an index."); throw new ConfigurationException("Actually, only services are from type array and need an index."); } } /* (non-Javadoc) * @see at.gv.egiz.components.configuration.meta.api.ConfigurationModul#storeChanges(java.util.Map, java.util.Map, java.util.List) */ @Override public void storeChanges(Map changed, Map added, List deleted) throws ConfigurationStorageException { logger.debug("Start configuration saving process ..."); MOAIDConfigurationValidator configValidator = new MOAIDConfigurationValidator(); if (deleted == null) deleted = new ArrayList(); int numOfGroups = configValidator.preProcess(changed, added, deleted); if (configValidator.getPreProcessedConfigurationData() != null && numOfGroups > 0) { logger.trace("Validate {} groups of key/value pairs", numOfGroups); try { configValidator.validate(); } catch (ConfigurationValidationException e) { logger.warn("Validation of MOA-ID configuration FAILED."); //TODO: update ConfigurationStorageException to add specific information of validation errors throw new ConfigurationStorageException(e.getFormatedErrorMessage(), e, false, false); } try { logger.trace("PreProcess configuration before saving."); Map configToStore = configValidator.postProcessing(deleted); //store all keys logger.debug("Store {} key/value pairs to configuration", configToStore.size()); Iterator> storageInterator = configToStore.entrySet().iterator(); while (storageInterator.hasNext()) { Entry el = storageInterator.next(); try { config.setStringValue(el.getKey(), el.getValue()); logger.trace("Store key: " + el.getKey() + " with value: " + el.getValue()); } catch (ConfigurationException e) { logger.error("Store key: " + el.getKey() + " with value: " + el.getValue() + " FAILED.", e); } } //delete all unused keys deleteEntries(deleted); } catch (Exception e) { logger.warn("Configuration post-processing FAILED.", e); throw new ConfigurationStorageException("Configuration can not be stored.", e); } } else if (deleted != null && deleted.size() > 0) { deleteEntries(deleted); } else { logger.info("Configuration saving process finished without operations: No key/value pairs found."); } } private void deleteEntries(List deleted) { if (deleted != null) { logger.debug("Delete {} keys pairs from configuration", deleted.size()); Iterator deleteInterator = deleted.iterator(); while (deleteInterator.hasNext()) { String el = deleteInterator.next(); try { config.deleteIds(el); logger.trace("Delete key {}", el); } catch (ConfigurationException e) { logger.error("Delete key: " + el + " FAILED.", e); } } } } private void loadType(String name, String resource) { InputStream is = null; try { SchemaEntry entry = new SchemaEntry(); is = MOAIDConfigurationModul.class.getResourceAsStream(resource); entry.jsonSchema = IOUtils.toString(is); entry.typeName = name; schemaList.add(entry); } catch (IOException e) { logger.error("Failed to load Type OA!", e); } finally { IOUtils.closeQuietly(is); } } }