/* * Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. * * Licensed 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.wso2.carbon.governance.registry.extensions.executors; import org.apache.axiom.om.OMAbstractFactory; import org.apache.axiom.om.OMAttribute; import org.apache.axiom.om.OMElement; import org.apache.axiom.om.OMFactory; import org.apache.axiom.om.util.AXIOMUtil; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.wso2.carbon.governance.api.util.GovernanceConstants; import org.wso2.carbon.governance.registry.extensions.aspects.utils.LifecycleConstants; import org.wso2.carbon.governance.registry.extensions.aspects.utils.StatCollection; import org.wso2.carbon.governance.registry.extensions.aspects.utils.StatWriter; import org.wso2.carbon.governance.registry.extensions.executors.utils.Utils; import org.wso2.carbon.governance.registry.extensions.interfaces.Execution; import org.wso2.carbon.registry.core.*; import org.wso2.carbon.registry.core.Collection; import org.wso2.carbon.registry.core.exceptions.RegistryException; import org.wso2.carbon.registry.core.jdbc.handlers.RequestContext; import org.wso2.carbon.registry.core.session.CurrentSession; import org.wso2.carbon.registry.core.utils.RegistryUtils; import org.wso2.carbon.registry.extensions.utils.CommonConstants; import org.wso2.carbon.registry.extensions.utils.CommonUtil; import javax.xml.stream.XMLStreamException; import java.util.*; import static org.wso2.carbon.governance.registry.extensions.aspects.utils.Utils.getHistoryInfoElement; import static org.wso2.carbon.governance.registry.extensions.executors.utils.ExecutorConstants.*; import static org.wso2.carbon.governance.registry.extensions.executors.utils.Utils.*; import static org.wso2.carbon.registry.extensions.utils.CommonUtil.setServiceVersion; public class SOAPServiceVersionExecutor implements Execution { private static final Log log = LogFactory.getLog(SOAPServiceVersionExecutor.class); // from the old code private String serviceMediaType = "application/vnd.wso2-soap-service+xml"; // To track whether we need to move comments,tags,ratings and all the associations. private boolean copyComments = false; private boolean copyTags = false; private boolean copyRatings = false; private boolean copyAllAssociations = false; private boolean copyDependencies = true; private boolean override = false; private static final String ASSOCIATION = "association"; private static final String LIFECYCLE_ASPECT_NAME= "registry.LC.name"; private boolean isAuditEnabled = true; private Map parameterMap = new HashMap(); public void init(Map parameterMap) { //To change body of implemented methods use File | Settings | File Templates. this.parameterMap = parameterMap; if (parameterMap.get(SERVICE_MEDIA_TYPE_KEY) != null) { serviceMediaType = parameterMap.get(SERVICE_MEDIA_TYPE_KEY).toString(); } if (parameterMap.get(COPY_COMMENTS) != null) { copyComments = Boolean.parseBoolean((String) parameterMap.get(COPY_COMMENTS)); } if (parameterMap.get(COPY_TAGS) != null) { copyTags = Boolean.parseBoolean((String) parameterMap.get(COPY_TAGS)); } if (parameterMap.get(COPY_RATINGS) != null) { copyRatings = Boolean.parseBoolean((String) parameterMap.get(COPY_RATINGS)); } if (parameterMap.get(COPY_ASSOCIATIONS) != null) { copyAllAssociations = Boolean.parseBoolean((String) parameterMap.get(COPY_ASSOCIATIONS)); } if (parameterMap.get(COPY_DEPENDENCIES) != null) { copyDependencies = Boolean.parseBoolean((String) parameterMap.get(COPY_DEPENDENCIES)); } if (parameterMap.get(OVERRIDE) != null) { override = Boolean.parseBoolean((String) parameterMap.get(OVERRIDE)); } } public boolean execute(RequestContext requestContext, String currentState, String targetState) { // To keep track of the registry transaction state boolean transactionStatus = false; OMElement historyOperation = null; List<String> otherDependencyList = new ArrayList<String>(); // for logging purposes try { historyOperation = AXIOMUtil.stringToOM("<operation></operation>"); } catch (XMLStreamException e) { log.error(e); } // getting the necessary values from the request context Resource resource = requestContext.getResource(); Registry registry = requestContext.getRegistry(); String resourcePath = requestContext.getResourcePath().getPath(); Map<String, String> currentParameterMap = new HashMap<String, String>(); Map<String, String> newPathMappings; // Returning true since this executor is not compatible with collections if (resource instanceof Collection) { return true; } else if (resource.getMediaType() == null || "".equals(resource.getMediaType().trim())) { log.warn("The media-type of the resource '" + resourcePath + "' is undefined. Hence exiting the service version executor."); return true; } else if (!resource.getMediaType().equals(serviceMediaType)) { // We have a generic copy executor to copy any resource type. // This executor is written for services. // If a resource other than a service comes here, then we simply return true // since we can not handle it using this executor. return true; } // Getting the target environment and the current environment from the parameter map. String targetEnvironment = RegistryUtils.getAbsolutePath(registry.getRegistryContext(), (String) parameterMap.get(TARGET_ENVIRONMENT)); String currentEnvironment = RegistryUtils.getAbsolutePath(registry.getRegistryContext(), (String) parameterMap.get(CURRENT_ENVIRONMENT)); if ((targetEnvironment == null || currentEnvironment == null) || (currentEnvironment.isEmpty() || targetEnvironment.isEmpty())) { log.warn("Current environment and the Target environment has not been defined to the state"); // Here we are returning true because the executor has been configured incorrectly // We do NOT consider that as a execution failure // Hence returning true here return true; } // Here we are populating the parameter map that was given from the UI if (!populateParameterMap(requestContext, currentParameterMap)) { log.error("Failed to populate the parameter map"); return false; } try { // Starting a registry transaction registry.beginTransaction(); Resource newResource = registry.newResource(); // This loop is there to reformat the paths with the new versions. newPathMappings = getNewPathMappings(targetEnvironment, currentEnvironment, currentParameterMap, otherDependencyList); // Once the paths are updated with the new versions we do through the service resource and update the // content of the service resource with the new service version, wsdl path. if (!CommonUtil.isUpdateLockAvailable()) { return false; } CommonUtil.acquireUpdateLock(); try { // Iterating through the list of dependencies for (Map.Entry<String, String> currentParameterMapEntry : currentParameterMap.entrySet()) { if (registry.resourceExists(currentParameterMapEntry.getKey())) { String newTempResourcePath; Resource tempResource = registry.get(currentParameterMapEntry.getKey()); if (!(tempResource instanceof Collection) && tempResource.getMediaType() != null) { updateNewPathMappings(tempResource.getMediaType(), currentEnvironment, targetEnvironment, newPathMappings, currentParameterMapEntry.getKey(), currentParameterMapEntry.getValue()); } StringBuilder resourceContent = new StringBuilder(getResourceContent(tempResource)); // Update resource content to reflect new paths for (Map.Entry<String, String> newPathMappingsEntry : newPathMappings.entrySet()) { if (resourceContent != null && !ENDPOINT_MEDIA_TYPE.equals(tempResource.getMediaType())) { int index; if ((index = resourceContent.indexOf(newPathMappingsEntry.getKey())) > -1) { resourceContent.replace(index, index + newPathMappingsEntry.getKey().length() , newPathMappingsEntry.getValue()); } else if (SCHEMA_MEDIA_TYPE.equals(tempResource.getMediaType())) { updateSchemaRelativePaths(targetEnvironment, currentEnvironment, resourceContent, newPathMappingsEntry); } else if (WSDL_MEDIA_TYPE.equals(tempResource.getMediaType())) { updateWSDLRelativePaths(targetEnvironment, currentEnvironment, resourceContent, newPathMappingsEntry); } } } tempResource.setContent(resourceContent.toString()); newTempResourcePath = newPathMappings.get(tempResource.getPath()); // Checking whether this resource is a service resource // If so, then we handle it in a different way if ((tempResource.getMediaType() != null) && (tempResource.getMediaType().equals(serviceMediaType))) { newResource = tempResource; OMElement serviceElement = getServiceOMElement(newResource); OMFactory fac = OMAbstractFactory.getOMFactory(); // Adding required fields at the top of the xml which will help to easily read in service side Iterator it = serviceElement.getChildrenWithLocalName("newServicePath"); if (it.hasNext()) { OMElement next = (OMElement) it.next(); next.setText(newTempResourcePath); } else { OMElement operation = fac.createOMElement("newServicePath", serviceElement.getNamespace(), serviceElement); operation.setText(newTempResourcePath); } setServiceVersion(serviceElement, currentParameterMap.get(tempResource.getPath())); // This is here to override the default path serviceElement.build(); resourceContent = new StringBuilder(serviceElement.toString()); newResource.setContent(resourceContent.toString()); addNewId(registry, newResource, newTempResourcePath); continue; } addNewId(registry, tempResource, newTempResourcePath); // We add all the resources other than the original one here if (!tempResource.getPath().equals(resourcePath)) { // adding logs historyOperation.addChild(getHistoryInfoElement(newTempResourcePath + " created")); registry.put(newTempResourcePath, tempResource); // copyCommunityFeatures(requestContext, registry, resourcePath, newPathMappings, historyOperation); copyComments(registry,newTempResourcePath,currentParameterMapEntry.getKey(),historyOperation); copyRatings(requestContext.getSystemRegistry(),newTempResourcePath,currentParameterMapEntry.getKey(),historyOperation); copyAllAssociations(registry,newTempResourcePath,currentParameterMapEntry.getKey(),historyOperation); } } } // We check whether there is a resource with the same name,namespace and version in this environment // if so, we make it return false based on override flag. if (registry.resourceExists(newPathMappings.get(resourcePath)) & !override) { // This means that we should not do this operation and we should fail this String message = "A resource exists with the given version"; requestContext.setProperty(LifecycleConstants.EXECUTOR_MESSAGE_KEY, message); throw new RegistryException(message); } // This is to handle the original resource and put it to the new path registry.put(newPathMappings.get(resourcePath), newResource); historyOperation.addChild(getHistoryInfoElement(newPathMappings.get(resourcePath) + " created")); // Initializing statCollection object StatCollection statCollection = new StatCollection(); // Set action type="association" statCollection.setActionType(ASSOCIATION); statCollection.setAction(""); statCollection.setRegistry(registry.getRegistryContext().getEmbeddedRegistryService() .getSystemRegistry(CurrentSession.getTenantId())); statCollection.setTimeMillis(System.currentTimeMillis()); statCollection.setState(currentState); statCollection.setResourcePath(newPathMappings.get(resourcePath)); statCollection.setUserName(CurrentSession.getUser()); statCollection.setOriginalPath(newPathMappings.get(resourcePath)); statCollection.setTargetState(targetState); statCollection.setAspectName(resource.getProperty(LIFECYCLE_ASPECT_NAME)); // Writing the logs to the registry as history if (isAuditEnabled) { StatWriter.writeHistory(statCollection); } } finally { CommonUtil.releaseUpdateLock(); } // Associating the new resource with the LC String aspectName = resource.getProperty(REGISTRY_LC_NAME); registry.associateAspect(newPathMappings.get(resourcePath) , aspectName); makeDependencies(requestContext, currentParameterMap, newPathMappings); makeOtherDependencies(requestContext, newPathMappings, otherDependencyList); // Here we are coping the comments,tags,rating and associations of the original resource copyCommunityFeatures(requestContext, registry, resourcePath, newPathMappings, historyOperation); addSubscriptionAvailableProperty(newResource); requestContext.setResource(newResource); requestContext.setOldResource(resource); requestContext.setResourcePath(new ResourcePath(newPathMappings.get(resourcePath))); // adding logs StatCollection statCollection = (StatCollection) requestContext.getProperty(LifecycleConstants.STAT_COLLECTION); // keeping the old path due to logging purposes newResource.setProperty(LifecycleConstants.REGISTRY_LIFECYCLE_HISTORY_ORIGINAL_PATH + aspectName, statCollection.getOriginalPath()); statCollection.addExecutors(this.getClass().getName(), historyOperation); transactionStatus = true; } catch (RegistryException e) { log.error("Failed to perform registry operation", e); return false; } finally { try { if (transactionStatus) { registry.commitTransaction(); } else { registry.rollbackTransaction(); } } catch (RegistryException e) { log.error("Unable to finish the transaction", e); } } return true; } private void copyCommunityFeatures(RequestContext requestContext, Registry registry, String resourcePath, Map<String, String> newPathMappings, OMElement historyOperation) throws RegistryException { copyComments(registry, newPathMappings.get(resourcePath), resourcePath, historyOperation); copyTags(registry, newPathMappings.get(resourcePath), resourcePath, historyOperation); copyRatings(requestContext.getSystemRegistry(), newPathMappings.get(resourcePath), resourcePath, historyOperation); // We avoid copying dependencies here because they are added to the new resources copyAllAssociations(registry, newPathMappings.get(resourcePath), resourcePath, historyOperation); } private void addSubscriptionAvailableProperty(Resource newResource) throws RegistryException { newResource.setProperty(GovernanceConstants.REGISTRY_IS_ENVIRONMENT_CHANGE, "true"); } private void copyAllAssociations(Registry registry, String newPath, String path, OMElement historyOperation) throws RegistryException { if (copyAllAssociations) { Utils.copyAssociations(registry, newPath, path); historyOperation.addChild(getHistoryInfoElement("All associations copied")); } } private void copyRatings(Registry registry, String newPath, String path, OMElement historyOperation) throws RegistryException { if (copyRatings) { Utils.copyRatings(registry, newPath, path); historyOperation.addChild(getHistoryInfoElement("Average rating copied")); } } private void copyTags(Registry registry, String newPath, String path, OMElement historyOperation) throws RegistryException { if (copyTags) { Utils.copyTags(registry, newPath, path); historyOperation.addChild(getHistoryInfoElement("Tags copied")); } } private void copyComments(Registry registry, String newPath, String path, OMElement historyOperation) throws RegistryException { if (copyComments) { Utils.copyComments(registry, newPath, path); historyOperation.addChild(getHistoryInfoElement("Comments copied")); } } private void updateNewPathMappings(String mediaType, String currentExpression, String targetExpression, Map<String, String> newPathMappingsMap, String resourcePath, String version) throws RegistryException { boolean hasValue = false; if (parameterMap.containsKey(mediaType + ":" + CURRENT_ENVIRONMENT)) { hasValue = true; currentExpression = (String) parameterMap.get(mediaType + ":" + CURRENT_ENVIRONMENT); } if (parameterMap.containsKey(mediaType + ":" + TARGET_ENVIRONMENT)) { hasValue = true; targetExpression = (String) parameterMap.get(mediaType + ":" + TARGET_ENVIRONMENT); } if (hasValue) { String path = reformatPath(resourcePath, currentExpression, targetExpression, version); newPathMappingsMap.put(resourcePath, path); } } private void updateSchemaRelativePaths(String targetEnvironment, String currentEnvironment, StringBuilder resourceContent, Map.Entry<String, String> newPathMappingsEntry) { try { OMElement contentElement = AXIOMUtil.stringToOM(resourceContent.toString()); updateRelativePath(targetEnvironment, currentEnvironment, contentElement, newPathMappingsEntry); resourceContent.replace(0, resourceContent.length(), contentElement.toString()); } catch (XMLStreamException e) { log.error(e); } } private OMElement updateRelativePath(String targetEnvironment, String currentEnvironment, OMElement contentElement, Map.Entry<String, String> newPathMappingsEntry) throws XMLStreamException { List importNodes = evaluateXpath(contentElement, IMPORT_XPATH_STRING); for (Object node : importNodes) { OMElement nodeElement = (OMElement) node; updateRelativePathContent(targetEnvironment, currentEnvironment, newPathMappingsEntry, nodeElement); } return contentElement; } private void updateWSDLRelativePaths(String targetEnvironment, String currentEnvironment, StringBuilder resourceContent, Map.Entry<String, String> newPathMappingsEntry) { try { OMElement contentElement = AXIOMUtil.stringToOM(resourceContent.toString()); updateRelativePath(targetEnvironment, currentEnvironment, contentElement, newPathMappingsEntry); List SchemaNodes = evaluateXpath(contentElement, XSD_XPATH_STRING); for (Object schemaNode : SchemaNodes) { OMElement schema = (OMElement) schemaNode; updateRelativePath(targetEnvironment, currentEnvironment, schema, newPathMappingsEntry); } resourceContent.replace(0, resourceContent.length(), contentElement.toString()); } catch (XMLStreamException e) { log.error(e); } } private void updateRelativePathContent(String targetEnvironment, String currentEnvironment, Map.Entry<String, String> newPathMappingsEntry, OMElement nodeElement) { Iterator it = nodeElement.getAllAttributes(); while (it.hasNext()) { OMAttribute next = (OMAttribute) it.next(); if (next.getLocalName().equals("location") || next.getLocalName().equals("schemaLocation")) { String relativePath = next.getAttributeValue(); String originalRelativePath = getOriginalRelativePath(currentEnvironment, newPathMappingsEntry); String newRelativePath = null; if (relativePath.equals(originalRelativePath)) { newRelativePath = getNewRelativePath(targetEnvironment, newPathMappingsEntry, null); }else if(relativePath.endsWith(originalRelativePath)){ String prefix = relativePath.replace(originalRelativePath,""); newRelativePath = prefix + getNewRelativePath(targetEnvironment,newPathMappingsEntry,null); }else { boolean contains = false; String[] relativePathSegments = relativePath.split(RegistryConstants.PATH_SEPARATOR); String[] originalSegments = originalRelativePath.split(RegistryConstants.PATH_SEPARATOR); String temp = originalRelativePath; for (int i = 0; i < originalSegments.length; i++) { temp = temp.substring(temp.indexOf(RegistryConstants.PATH_SEPARATOR) + 1); if(relativePath.endsWith(temp)){ contains = true; break; } } if (contains) { List<String> unwantedSegments = new ArrayList<String>(); for (String segment : originalSegments) { if (!relativePath.contains(RegistryConstants.PATH_SEPARATOR + segment + RegistryConstants.PATH_SEPARATOR) & !relativePath.endsWith(segment)) { unwantedSegments.add(segment); } } newRelativePath = getNewRelativePath(targetEnvironment, newPathMappingsEntry, unwantedSegments); if(originalSegments.length > relativePathSegments.length){ for(int i =0;i< originalSegments.length - relativePathSegments.length ; i++){ newRelativePath = newRelativePath.substring( newRelativePath.indexOf(RegistryConstants.PATH_SEPARATOR) +1); } } } } if (newRelativePath != null) { next.setAttributeValue(newRelativePath); } } } } private String getNewRelativePath(String targetEnvironment, Map.Entry<String, String> newPathMappingsEntry, List<String> unwantedSegments) { StringBuilder targetBuffer = new StringBuilder(); String targetPrefix = targetEnvironment.substring(0, targetEnvironment.indexOf(RESOURCE_PATH)); String replacementValue = newPathMappingsEntry.getValue().replace(targetPrefix, ""); targetPrefix = targetPrefix.substring(RegistryConstants.GOVERNANCE_REGISTRY_BASE_PATH.length() + 1); int targetPrefixPathSegments = targetPrefix.split(RegistryConstants.PATH_SEPARATOR).length; for (int i = 1; i < targetPrefixPathSegments; i++) { targetBuffer.append(".." + RegistryConstants.PATH_SEPARATOR); } if (unwantedSegments != null) { for (String unwantedSegment : unwantedSegments) { replacementValue = replacementValue.replaceFirst(unwantedSegment, ".."); } } return targetBuffer.toString() + replacementValue; } private String getOriginalRelativePath(String currentEnvironment, Map.Entry<String, String> newPathMappingsEntry) { String prefix = currentEnvironment.substring(0, currentEnvironment.indexOf(RESOURCE_PATH)); String pathSuffix = (newPathMappingsEntry.getKey()).replace(prefix, ""); StringBuilder sourceBuffer = new StringBuilder(); prefix = prefix.substring(RegistryConstants.GOVERNANCE_REGISTRY_BASE_PATH.length() + 1); int prefixPathSegments = prefix.split(RegistryConstants.PATH_SEPARATOR).length; for (int i = 1; i < prefixPathSegments; i++) { sourceBuffer.append(".." + RegistryConstants.PATH_SEPARATOR); } return sourceBuffer.toString() + pathSuffix; } private Map<String, String> getNewPathMappings(String targetEnvironment, String currentEnvironment , Map<String, String> currentParameterMap, List<String> otherDependencyList) throws RegistryException { Map<String, String> newPathMappingsMap = new HashMap<String, String>(); for (Map.Entry<String, String> keyValueSet : currentParameterMap.entrySet()) { String path = reformatPath(keyValueSet.getKey(), currentEnvironment, targetEnvironment, keyValueSet.getValue()); // This condition is there to check whether we need to move the resources // The executor will not execute beyond this point, to all the resources that are not under the given environment prefix if (path.equals(keyValueSet.getKey())) { log.info("Resource " + path + " is not in the given environment"); otherDependencyList.add(path); continue; } newPathMappingsMap.put(keyValueSet.getKey(), path); } for (String otherDependency : otherDependencyList) { currentParameterMap.remove(otherDependency); } return newPathMappingsMap; } private boolean populateParameterMap(RequestContext requestContext, Map<String, String> currentParameterMap) { Set parameterMapKeySet = (Set) requestContext.getProperty("parameterNames"); if (parameterMapKeySet == null) { if (serviceMediaType.equals(requestContext.getResource().getMediaType())) { if (getServiceOMElement(requestContext.getResource()) != null) { currentParameterMap.put(requestContext.getResource().getPath(), org.wso2.carbon.registry.common.utils.CommonUtil.getServiceVersion( getServiceOMElement(requestContext.getResource()))); return true; } } return false; } for (Object entry : parameterMapKeySet) { String key = (String) entry; if (!key.equals("preserveOriginal") && !key.endsWith(".item")) { currentParameterMap.put(key, (String) requestContext.getProperty(key)); } } if (currentParameterMap.isEmpty()) { if (serviceMediaType.equals(requestContext.getResource().getMediaType())) { if (getServiceOMElement(requestContext.getResource()) != null) { currentParameterMap.put(requestContext.getResource().getPath(), org.wso2.carbon.registry.common.utils.CommonUtil.getServiceVersion( getServiceOMElement(requestContext.getResource()))); // add if any dependencies are available for this resource under the version of the service if (copyDependencies) { try { Association[] associations = requestContext.getRegistry().getAllAssociations(requestContext.getResource().getPath()); if (associations != null && associations.length != 0) { for (Association association : associations) { if (association.getAssociationType().equals(CommonConstants.DEPENDS)) { if (requestContext.getResource().getPath().equals(association.getSourcePath())) { currentParameterMap.put(association.getDestinationPath(), org.wso2.carbon.registry.common.utils.CommonUtil.getServiceVersion( getServiceOMElement(requestContext.getResource()))); } } } } } catch (RegistryException e) { log.error(e); } } } } } return true; } /* * This method returns the target path. The target path is calculated from the given expression * When calculating the target path, we split the current path using the given current expression and then map the * path segments to the corresponding ones in the target path expression * */ private String reformatPath(String path, String currentExpression, String targetExpression, String newResourceVersion) throws RegistryException { TreeMap<Integer, String> indexMap = new TreeMap<Integer, String>(); String returnPath = targetExpression; String prefix; if (currentExpression.equals(targetExpression)) { return path; } indexMap.put(currentExpression.indexOf(RESOURCE_NAME), RESOURCE_NAME); indexMap.put(currentExpression.indexOf(RESOURCE_PATH), RESOURCE_PATH); indexMap.put(currentExpression.indexOf(RESOURCE_VERSION), RESOURCE_VERSION); String tempExpression = currentExpression; while (indexMap.lastKey() < tempExpression.lastIndexOf(RegistryConstants.PATH_SEPARATOR)) { tempExpression = tempExpression.substring(0, tempExpression.lastIndexOf(RegistryConstants.PATH_SEPARATOR)); path = path.substring(0, path.lastIndexOf(RegistryConstants.PATH_SEPARATOR)); } prefix = currentExpression.substring(0, currentExpression.indexOf(indexMap.get(indexMap.higherKey(-1)))); if (!path.startsWith(prefix)) { return path; } path = path.replace(prefix, ""); while (true) { if (indexMap.firstKey() < 0) { indexMap.pollFirstEntry(); } else { break; } } while (true) { if (indexMap.size() == 0) { break; } Map.Entry lastEntry = indexMap.pollLastEntry(); if (lastEntry.getValue().equals(RESOURCE_PATH)) { String pathValue = path; for (int i = 0; i < indexMap.size(); i++) { // pathValue = formatPath(pathValue.substring(path.indexOf(RegistryConstants.PATH_SEPARATOR))); pathValue = formatPath(pathValue.substring(pathValue.indexOf(RegistryConstants.PATH_SEPARATOR))); } if (!pathValue.equals("")) { returnPath = returnPath.replace(RESOURCE_PATH, formatPath(pathValue)); path = path.replace(pathValue, ""); } else { returnPath = returnPath.replace("/" + lastEntry.getValue(), ""); } continue; } if (lastEntry.getValue().equals(RESOURCE_VERSION)) { returnPath = returnPath.replace(RESOURCE_VERSION, newResourceVersion); if (path.contains("/")) { path = path.substring(0, path.lastIndexOf(RegistryConstants.PATH_SEPARATOR)); } else { path = ""; } continue; } String tempPath; if (path.contains("/")) { tempPath = path.substring(path.lastIndexOf(RegistryConstants.PATH_SEPARATOR) + 1); } else { tempPath = path; } if (!tempPath.equals("")) { returnPath = returnPath.replace((String) lastEntry.getValue(), formatPath(tempPath)); if (path.contains("/")) { path = path.substring(0, path.lastIndexOf(RegistryConstants.PATH_SEPARATOR)); } else { path = ""; } } else { returnPath = returnPath.replace("/" + lastEntry.getValue(), ""); if (path.contains("/")) { path = path.substring(0, path.lastIndexOf(RegistryConstants.PATH_SEPARATOR)); } } } // Adding the version validation here. if(!newResourceVersion.matches("^\\d+[.]\\d+[.]\\d+(-[a-zA-Z0-9]+)?$")){ String message = "Invalid version found for " + RegistryUtils.getResourceName(path); log.error(message); throw new RegistryException(message); } if (returnPath.contains(RESOURCE_VERSION)) { return returnPath.replace(RESOURCE_VERSION, newResourceVersion); } return returnPath; } }