package com.temenos.interaction.springdsl; /* * #%L * interaction-springdsl * %% * Copyright (C) 2012 - 2016 Temenos Holdings N.V. * %% * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * #L% */ import com.temenos.interaction.core.cache.CacheExtended; import com.temenos.interaction.core.hypermedia.ResourceState; import com.temenos.interaction.core.loader.ResourceStateLoadingStrategy; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.core.io.Resource; import org.springframework.core.io.support.PathMatchingResourcePatternResolver; import org.springframework.core.io.support.ResourcePatternResolver; import java.io.IOException; import java.nio.file.Paths; import java.util.*; import static com.temenos.interaction.core.loader.ResourceStateLoadingStrategy.ResourceStateResult; /** * Provider of ResourceState that loads all of them at instantiation time from * the PRD files matching the ant style pattern. It allows to plug-in different * cache strategies, as well as loading strategies (although the only loading * strategy that makes sense here is a Spring one). * * The class currently extends SpringDSLResourceStateProvider for code re-usage. * This is a temporary solution until major re-factoring is done. * * @author kwieconkowski * @author andres * @author dgroves */ public class EagerSpringDSLResourceStateProvider extends SpringDSLResourceStateProvider { private final Logger logger = LoggerFactory.getLogger(EagerSpringDSLResourceStateProvider.class); private final CacheExtended<String, ResourceState> cache; private final String antStylePattern; private Set<String> PRDconfigurationFileSources; private ResourceStateLoadingStrategy<String> loadingStrategy; public EagerSpringDSLResourceStateProvider(String antStylePattern, ResourceStateLoadingStrategy<String> loadingStrategy, CacheExtended<String, ResourceState> cache) { this(antStylePattern, loadingStrategy, cache, null); } public EagerSpringDSLResourceStateProvider(String antStylePattern, ResourceStateLoadingStrategy<String> loadingStrategy, CacheExtended<String, ResourceState> cache, Properties beanMap) { super(beanMap); this.antStylePattern = antStylePattern; this.loadingStrategy = loadingStrategy; this.cache = cache; PRDconfigurationFileSources = new LinkedHashSet(); discoverAllPrdFilesNames(); loadAllResourceStates(); } public void setLoadingStrategy(ResourceStateLoadingStrategy<String> loadingStrategy) { this.loadingStrategy = loadingStrategy; } @Override public ResourceState getResourceState(String resourceStateName) { logger.info("Getting resource state name: " + resourceStateName); ResourceState resourceState = getResourceStateByNameOrByOldFormatName(resourceStateName); if (resourceState == null) { logger.error("Could not find resource state name: " + resourceStateName); } return resourceState; } private ResourceState getResourceStateByNameOrByOldFormatName(String resourceStateName) { ResourceState resourceState = cache.get(resourceStateName); return resourceState != null ? resourceState : getResourceStateByOldFormat(resourceStateName); } private ResourceState getResourceStateByOldFormat(String resourceStateName) { ResourceState resourceState = null; String oldResourceStateName = resourceStateName; oldResourceStateName = substringToFirstLineSymbol(oldResourceStateName); resourceState = cache.get(oldResourceStateName); if (resourceState == null) { oldResourceStateName = replaceLastUnderscoreWithLine(oldResourceStateName); resourceState = cache.get(oldResourceStateName); } return resourceState; } private String replaceLastUnderscoreWithLine(String resourceStateName) { if (!isThereLineSymbol(resourceStateName)) { int pos = resourceStateName.lastIndexOf("_"); if (pos > 0) { resourceStateName = String.format("%s-%s", resourceStateName.substring(0, pos), resourceStateName.substring(pos + 1)); } } return resourceStateName; } private boolean isThereLineSymbol(String resourceStateName) { return resourceStateName.lastIndexOf("-") >= 0; } private String substringToFirstLineSymbol(String newResourceStateName) { if (newResourceStateName.contains("-")) { newResourceStateName = newResourceStateName.substring(0, newResourceStateName.indexOf("-")); } return newResourceStateName; } @Override public void unload(String resourceStateName) { cache.remove(resourceStateName); } @Override public void addState(String stateName, Properties properties) { String[] methodAndPath = properties.getProperty(stateName).split(" "); String[] methods = methodAndPath[0].split(","); String path = methodAndPath[1]; logger.info(String.format("Attempting to register state: %s, methods: %s, path: %s, using state registeration: %s", stateName, methods, path, stateRegisteration != null ? stateRegisteration : "NULL")); if (!loadResourceStatesFromPRD(discoverNameOfPrdByUsingResourceStateName(stateName, false)) && !loadResourceStatesFromPRD(discoverNameOfPrdByUsingResourceStateName(stateName, true))) { logger.error("None of discovered PRD configuration xml file names is valid"); return; } // populate maps in parent class from properties files storeState(stateName, properties.getProperty(stateName)); stateRegisteration.register(stateName, path, new HashSet<String>(Arrays.asList(methods))); } @Override public boolean isLoaded(String resourceStateName) { return (cache.get(resourceStateName) != null); } /* Reload resource states from prd files (clear old ones from cache before) */ private synchronized void loadAllResourceStates() { cache.removeAll(); for (String locationOfPRD : PRDconfigurationFileSources) { loadResourceStatesFromPRD(locationOfPRD); } } private String discoverNameOfPrdByUsingResourceStateName(String resourceStateName, boolean oldFormat) { String pathToPRD = null; String newResourceStateName = resourceStateName; newResourceStateName = substringToFirstLineSymbol(newResourceStateName); if (!oldFormat) { return String.format("IRIS-%s-PRD.xml", newResourceStateName); } pathToPRD = substringToFirstUnderscoreSymbol(newResourceStateName); return pathToPRD; } private String substringToFirstUnderscoreSymbol(String newResourceStateName) { int position = newResourceStateName.lastIndexOf("_"); if (position > 3) { return String.format("IRIS-%s-PRD.xml", newResourceStateName.substring(0, position)); } return null; } private boolean loadResourceStatesFromPRD(String prdName) { List<ResourceStateResult> resourceStates = null; Map<String, ResourceState> tmp = new HashMap<String, ResourceState>(); if (prdName == null) { return false; } logger.info("Loading PRD file: " + prdName); resourceStates = loadingStrategy.load(prdName); if (resourceStates == null) { logger.warn("Could not find any resources with name: " + prdName); return false; } for (ResourceStateResult resourceStateResult : resourceStates) { tmp.put(resourceStateResult.resourceStateId, resourceStateResult.resourceState); } cache.putAll(tmp); return true; } private void discoverAllPrdFilesNames() { final ResourcePatternResolver patternResolver = new PathMatchingResourcePatternResolver(); final Resource[] locationsPRD; try { String fileName; locationsPRD = patternResolver.getResources(antStylePattern); if (locationsPRD != null) { PRDconfigurationFileSources.clear(); for (int i = 0; i < locationsPRD.length; i++) { fileName = Paths.get(locationsPRD[i].getURI().getPath().substring(1)).getFileName().toString(); PRDconfigurationFileSources.add(fileName); logger.info("Discovered path to PRD file: " + fileName); } } else { logger.warn("There was not found any PRD configuration xml files using given antStylePattern"); } } catch (IOException e) { String msg = "IOException while loading PRD configuration xml files"; logger.error(msg, e); throw new IllegalStateException(msg, e); } } }