From a32242f612b4191ae92ab7654bd69f70bde56163 Mon Sep 17 00:00:00 2001 From: cnapagoda Date: Fri, 19 Jun 2015 12:54:20 +0530 Subject: [PATCH] Fix for REGISTRY-2602 --- .../lifecycle_aspect_ajaxprocessor.jsp | 271 +++++++ .../executors/SOAPServiceVersionExecutor.java | 674 ++++++++++++++++++ 2 files changed, 945 insertions(+) create mode 100644 components/governance/org.wso2.carbon.governance.custom.lifecycles.checklist.ui/src/main/resources/web/lifecycles/lifecycle_aspect_ajaxprocessor.jsp create mode 100644 components/governance/org.wso2.carbon.governance.registry.extensions/src/org/wso2/carbon/governance/registry/extensions/executors/SOAPServiceVersionExecutor.java diff --git a/components/governance/org.wso2.carbon.governance.custom.lifecycles.checklist.ui/src/main/resources/web/lifecycles/lifecycle_aspect_ajaxprocessor.jsp b/components/governance/org.wso2.carbon.governance.custom.lifecycles.checklist.ui/src/main/resources/web/lifecycles/lifecycle_aspect_ajaxprocessor.jsp new file mode 100644 index 000000000..1326ccd21 --- /dev/null +++ b/components/governance/org.wso2.carbon.governance.custom.lifecycles.checklist.ui/src/main/resources/web/lifecycles/lifecycle_aspect_ajaxprocessor.jsp @@ -0,0 +1,271 @@ + +<%@ page contentType="text/html;charset=UTF-8" language="java" %> +<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> +<%@ page import="org.wso2.carbon.governance.custom.lifecycles.checklist.ui.processors.InvokeAspectProcessor" %> +<%@ page import="org.wso2.carbon.registry.extensions.utils.CommonConstants" %> +<%@ page import="java.util.List" %> +<%@ page import="java.util.ArrayList" %> +<%@ page import="java.util.regex.Pattern" %> +<%@ page import="java.net.URLDecoder" %> +<%@ page import="org.wso2.carbon.registry.core.utils.RegistryUtils" %> +<% + try { + boolean isViewVersion = false; + boolean preserveOriginal = true; + boolean viewDependencies = true; + boolean viewPreserveOriginal = false; + String displayMediaType = ""; + String currentEnvironment = ""; + String[] preserveOrigParam = null; + String[] viewVersion = null; + String[] parameters = request.getParameterValues("parameterMap"); + + String path = request.getParameter("path"); + String aspect = request.getParameter("aspect"); + String action = request.getParameter("action"); + String callBack = request.getParameter("callBack"); + + if (callBack == null || callBack.trim().length() == 0) { + callBack = "''"; + } + + if (parameters != null) { + for (String parameter : parameters) { + parameter = URLDecoder.decode(parameter, "utf-8"); + if (parameter.contains("&")) { + String[] joinedParams = parameter.split("&"); + for (String joinedParam : joinedParams) { + if (joinedParam.split("=")[0].equals("preserveOriginal")) { + preserveOrigParam = joinedParam.split("="); + } else if (joinedParam.split("=")[0].equals("viewVersion")) { + viewVersion = joinedParam.split("="); + isViewVersion = !Boolean.parseBoolean(viewVersion[1]); + } else if(joinedParam.split("=")[0].equals("displayMediaType")){ + displayMediaType = joinedParam.split("=")[1]; + } else if(joinedParam.split("=")[0].equals("showDependencies")){ + viewDependencies = Boolean.parseBoolean(joinedParam.split("=")[1]); + } else if(joinedParam.split("=")[0].equals("viewPreserveOriginal")){ + viewPreserveOriginal = Boolean.parseBoolean(joinedParam.split("=")[1]); + }else if(joinedParam.split("=")[0].equals("currentEnvironment")){ + currentEnvironment = joinedParam.split("=")[1]; + } + } + } else { + if (parameter.split("=")[0].equals("preserveOriginal")) { + preserveOrigParam = parameter.split("="); + } else if (parameter.split("=")[0].equals("viewVersion")) { + viewVersion = parameters[0].split("="); + isViewVersion = !Boolean.parseBoolean(viewVersion[1]); + }else if(parameter.split("=")[0].equals("displayMediaType")){ + displayMediaType = parameter.split("=")[1]; + } else if(parameter.split("=")[0].equals("showDependencies")){ + viewDependencies = Boolean.parseBoolean(parameter.split("=")[1]); + } else if(parameter.split("=")[0].equals("viewPreserveOriginal")){ + viewPreserveOriginal = Boolean.parseBoolean(parameter.split("=")[1]); + }else if(parameter.split("=")[0].equals("currentEnvironment")){ + currentEnvironment = parameter.split("=")[1]; + } + } + } + } + + if (preserveOrigParam != null) { + String preserveOrg = ""; + if (preserveOrigParam[0].equals("preserveOriginal")) { + preserveOrg = preserveOrigParam[1]; + } + preserveOriginal = !Boolean.toString(false).equals(preserveOrg); + } + + if (isViewVersion) { + try { + String versionString = "preserveOriginal" + "^^" + preserveOriginal + "^|^"; + +%> + +<% + + } catch (Exception ex) { + ex.printStackTrace(); + response.setStatus(500); + ex.getMessage(); + return; + + } +%> +<% +} else { + String mediaType = request.getParameter("mediaType"); + if (preserveOrigParam != null && preserveOrigParam.length != 0) { + preserveOriginal = Boolean.parseBoolean(preserveOrigParam[1]); + } + List otherDependencies = new ArrayList(); + + if (displayMediaType == null || displayMediaType.equals("")) { + displayMediaType = CommonConstants.SOAP_SERVICE_MEDIA_TYPE.replace(".", "[.]").replace("+", "[+]"); + } + + if (!(Pattern.compile(displayMediaType).matcher(mediaType).find())) { +%> + +<% +} else { + String[] associations; + if (!viewDependencies) { + associations = new String[1]; + associations[0] = path; + } else { + associations = InvokeAspectProcessor.getAllDependencies(request, config); + } +%> + + + + +
+ + <% + if (associations.length > 0) { + %> + + + + + + + <% + for (String association : associations) { + String assoName = association.substring(association.lastIndexOf("/") + 1); + String tmp; + if(association.equals("/")) { + tmp = association; + } else { + tmp = association.substring(association.indexOf("/_system")); + } + if (currentEnvironment == null || tmp.startsWith(currentEnvironment)) { + %> + + + + + <% + } else { + otherDependencies.add(association); + } + } + if(viewPreserveOriginal){ + %> + + + + <% + } + %> + + + + <% + } + for (String otherDependency : otherDependencies) { + String assoName = otherDependency.substring(otherDependency.lastIndexOf("/") + 1); + %> + + <% + } + %> + +
ResourceVersion
+ <%=assoName%> + * + + +
: checked="checked" <%} %> value="true" + id="preserveOriginal"/>
+ " + value="" + onclick="proceedAction('<%=path%>', '<%=aspect%>', '<%=action%>','<%=mediaType%>', + '<%=preserveOriginal%>' ,<%=callBack%>)"/> + " + onclick="cancelVersionBox('<%=path%>', '<%=aspect%>')"/> +
+
+
+<% + } + } +} catch (Exception ex) { + ex.printStackTrace(); + response.setStatus(500); +%><%=ex.getMessage()%><% + return; + + } + + +%> \ No newline at end of file diff --git a/components/governance/org.wso2.carbon.governance.registry.extensions/src/org/wso2/carbon/governance/registry/extensions/executors/SOAPServiceVersionExecutor.java b/components/governance/org.wso2.carbon.governance.registry.extensions/src/org/wso2/carbon/governance/registry/extensions/executors/SOAPServiceVersionExecutor.java new file mode 100644 index 000000000..fe4031350 --- /dev/null +++ b/components/governance/org.wso2.carbon.governance.registry.extensions/src/org/wso2/carbon/governance/registry/extensions/executors/SOAPServiceVersionExecutor.java @@ -0,0 +1,674 @@ +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 otherDependencyList = new ArrayList(); +// for logging purposes + try { + historyOperation = AXIOMUtil.stringToOM(""); + } 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 currentParameterMap = new HashMap(); + Map 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 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 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 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 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 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 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 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 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 unwantedSegments = new ArrayList(); + + 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 newPathMappingsEntry, + List 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 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 getNewPathMappings(String targetEnvironment, String currentEnvironment + , Map currentParameterMap, List otherDependencyList) throws RegistryException { + + Map newPathMappingsMap = new HashMap(); + + for (Map.Entry 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 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 indexMap = new TreeMap(); + + 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; + } +} \ No newline at end of file