diff options
Diffstat (limited to 'cps-service/src/main/java')
16 files changed, 358 insertions, 30 deletions
diff --git a/cps-service/src/main/java/org/onap/cps/api/CpsAdminService.java b/cps-service/src/main/java/org/onap/cps/api/CpsAdminService.java index 44f7f77152..2106f1584e 100755 --- a/cps-service/src/main/java/org/onap/cps/api/CpsAdminService.java +++ b/cps-service/src/main/java/org/onap/cps/api/CpsAdminService.java @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2020 Nordix Foundation + * Copyright (C) 2020-2022 Nordix Foundation * Modifications Copyright (C) 2020-2022 Bell Canada. * Modifications Copyright (C) 2021 Pantheon.tech * ================================================================================ @@ -23,9 +23,11 @@ package org.onap.cps.api; import java.util.Collection; +import java.util.Set; import org.onap.cps.spi.exceptions.AlreadyDefinedException; import org.onap.cps.spi.exceptions.CpsException; import org.onap.cps.spi.model.Anchor; +import org.onap.cps.spi.model.CmHandleQueryParameters; /** * CPS Admin Service. @@ -100,4 +102,12 @@ public interface CpsAdminService { * given module names */ Collection<String> queryAnchorNames(String dataspaceName, Collection<String> moduleNames); + + /** + * Query and return cm handles that match the given query parameters. + * + * @param cmHandleQueryParameters the cm handle query parameters + * @return collection of cm handle ids + */ + Set<String> queryCmHandles(CmHandleQueryParameters cmHandleQueryParameters); } diff --git a/cps-service/src/main/java/org/onap/cps/api/CpsDataService.java b/cps-service/src/main/java/org/onap/cps/api/CpsDataService.java index cdd417bd8d..93c96ec650 100644 --- a/cps-service/src/main/java/org/onap/cps/api/CpsDataService.java +++ b/cps-service/src/main/java/org/onap/cps/api/CpsDataService.java @@ -174,4 +174,41 @@ public interface CpsDataService { */ void updateNodeLeavesAndExistingDescendantLeaves(String dataspaceName, String anchorName, String parentNodeXpath, String dataNodeUpdatesAsJson, OffsetDateTime observedTimestamp); + + /** + * Starts a session which allows use of locks and batch interaction with the persistence service. + * + * @return Session ID string + */ + String startSession(); + + /** + * Close session. + * + * @param sessionId session ID + * + */ + void closeSession(String sessionId); + + /** + * Lock anchor with default timeout. + * To release locks(s), the session holding the lock(s) must be closed. + * + * @param sessionID session ID + * @param dataspaceName dataspace name + * @param anchorName anchor name + */ + void lockAnchor(String sessionID, String dataspaceName, String anchorName); + + /** + * Lock anchor with custom timeout. + * To release locks(s), the session holding the lock(s) must be closed. + * + * @param sessionID session ID + * @param dataspaceName dataspace name + * @param anchorName anchor name + * @param timeoutInMilliseconds lock attempt timeout in milliseconds + */ + void lockAnchor(String sessionID, String dataspaceName, String anchorName, Long timeoutInMilliseconds); + } diff --git a/cps-service/src/main/java/org/onap/cps/api/CpsModuleService.java b/cps-service/src/main/java/org/onap/cps/api/CpsModuleService.java index ecc9bf0986..79d6e03d4a 100644 --- a/cps-service/src/main/java/org/onap/cps/api/CpsModuleService.java +++ b/cps-service/src/main/java/org/onap/cps/api/CpsModuleService.java @@ -23,7 +23,6 @@ package org.onap.cps.api; import java.util.Collection; import java.util.Map; -import org.checkerframework.checker.nullness.qual.NonNull; import org.onap.cps.spi.CascadeDeleteAllowed; import org.onap.cps.spi.exceptions.DataInUseException; import org.onap.cps.spi.model.ModuleReference; @@ -42,8 +41,8 @@ public interface CpsModuleService { * @param yangResourcesNameToContentMap yang resources (files) as a mep where key is resource name * and value is content */ - void createSchemaSet(@NonNull String dataspaceName, @NonNull String schemaSetName, - @NonNull Map<String, String> yangResourcesNameToContentMap); + void createSchemaSet(String dataspaceName, String schemaSetName, + Map<String, String> yangResourcesNameToContentMap); /** * Create a schema set from new modules and existing modules. @@ -52,8 +51,8 @@ public interface CpsModuleService { * @param newModuleNameToContentMap YANG resources map where key is a module name and value is content * @param moduleReferences List of YANG resources module references of the modules */ - void createSchemaSetFromModules(@NonNull String dataspaceName, @NonNull String schemaSetName, - @NonNull Map<String, String> newModuleNameToContentMap, + void createSchemaSetFromModules(String dataspaceName, String schemaSetName, + Map<String, String> newModuleNameToContentMap, Collection<ModuleReference> moduleReferences); /** @@ -63,7 +62,7 @@ public interface CpsModuleService { * @param schemaSetName schema set name * @return a SchemaSet */ - SchemaSet getSchemaSet(@NonNull String dataspaceName, @NonNull String schemaSetName); + SchemaSet getSchemaSet(String dataspaceName, String schemaSetName); /** * Deletes Schema Set. @@ -74,8 +73,8 @@ public interface CpsModuleService { * @throws DataInUseException if cascadeDeleteAllowed is set to CASCADE_DELETE_PROHIBITED and there * is associated anchor record exists in database */ - void deleteSchemaSet(@NonNull String dataspaceName, @NonNull String schemaSetName, - @NonNull CascadeDeleteAllowed cascadeDeleteAllowed); + void deleteSchemaSet(String dataspaceName, String schemaSetName, + CascadeDeleteAllowed cascadeDeleteAllowed); /** * Retrieve module references for the given dataspace name. diff --git a/cps-service/src/main/java/org/onap/cps/api/CpsQueryService.java b/cps-service/src/main/java/org/onap/cps/api/CpsQueryService.java index beb0a1540e..68ae1ebf0a 100644 --- a/cps-service/src/main/java/org/onap/cps/api/CpsQueryService.java +++ b/cps-service/src/main/java/org/onap/cps/api/CpsQueryService.java @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2020 Nordix Foundation + * Copyright (C) 2020-2022 Nordix Foundation * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,7 +21,6 @@ package org.onap.cps.api; import java.util.Collection; -import org.checkerframework.checker.nullness.qual.NonNull; import org.onap.cps.spi.FetchDescendantsOption; import org.onap.cps.spi.model.DataNode; @@ -40,7 +39,7 @@ public interface CpsQueryService { * included in the output * @return a collection of data nodes */ - Collection<DataNode> queryDataNodes(@NonNull String dataspaceName, @NonNull String anchorName, - @NonNull String cpsPath, @NonNull FetchDescendantsOption fetchDescendantsOption); + Collection<DataNode> queryDataNodes(String dataspaceName, String anchorName, + String cpsPath, FetchDescendantsOption fetchDescendantsOption); } diff --git a/cps-service/src/main/java/org/onap/cps/api/impl/CpsAdminServiceImpl.java b/cps-service/src/main/java/org/onap/cps/api/impl/CpsAdminServiceImpl.java index 1013addbe1..762754f9a8 100755 --- a/cps-service/src/main/java/org/onap/cps/api/impl/CpsAdminServiceImpl.java +++ b/cps-service/src/main/java/org/onap/cps/api/impl/CpsAdminServiceImpl.java @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2020 Nordix Foundation + * Copyright (C) 2020-2022 Nordix Foundation * Modifications Copyright (C) 2020-2022 Bell Canada. * Modifications Copyright (C) 2021 Pantheon.tech * ================================================================================ @@ -24,12 +24,15 @@ package org.onap.cps.api.impl; import java.time.OffsetDateTime; import java.util.Collection; +import java.util.Set; import java.util.stream.Collectors; import lombok.AllArgsConstructor; import org.onap.cps.api.CpsAdminService; import org.onap.cps.api.CpsDataService; import org.onap.cps.spi.CpsAdminPersistenceService; import org.onap.cps.spi.model.Anchor; +import org.onap.cps.spi.model.CmHandleQueryParameters; +import org.onap.cps.utils.CpsValidator; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Component; @@ -43,43 +46,56 @@ public class CpsAdminServiceImpl implements CpsAdminService { @Override public void createDataspace(final String dataspaceName) { + CpsValidator.validateNameCharacters(dataspaceName); cpsAdminPersistenceService.createDataspace(dataspaceName); } @Override public void deleteDataspace(final String dataspaceName) { + CpsValidator.validateNameCharacters(dataspaceName); cpsAdminPersistenceService.deleteDataspace(dataspaceName); } @Override public void createAnchor(final String dataspaceName, final String schemaSetName, final String anchorName) { + CpsValidator.validateNameCharacters(dataspaceName, schemaSetName, anchorName); cpsAdminPersistenceService.createAnchor(dataspaceName, schemaSetName, anchorName); } @Override public Collection<Anchor> getAnchors(final String dataspaceName) { + CpsValidator.validateNameCharacters(dataspaceName); return cpsAdminPersistenceService.getAnchors(dataspaceName); } @Override public Collection<Anchor> getAnchors(final String dataspaceName, final String schemaSetName) { + CpsValidator.validateNameCharacters(dataspaceName, schemaSetName); return cpsAdminPersistenceService.getAnchors(dataspaceName, schemaSetName); } @Override public Anchor getAnchor(final String dataspaceName, final String anchorName) { + CpsValidator.validateNameCharacters(dataspaceName, anchorName); return cpsAdminPersistenceService.getAnchor(dataspaceName, anchorName); } @Override public void deleteAnchor(final String dataspaceName, final String anchorName) { + CpsValidator.validateNameCharacters(dataspaceName, anchorName); cpsDataService.deleteDataNodes(dataspaceName, anchorName, OffsetDateTime.now()); cpsAdminPersistenceService.deleteAnchor(dataspaceName, anchorName); } @Override public Collection<String> queryAnchorNames(final String dataspaceName, final Collection<String> moduleNames) { + CpsValidator.validateNameCharacters(dataspaceName); final Collection<Anchor> anchors = cpsAdminPersistenceService.queryAnchors(dataspaceName, moduleNames); return anchors.stream().map(Anchor::getName).collect(Collectors.toList()); } + + @Override + public Set<String> queryCmHandles(final CmHandleQueryParameters cmHandleQueryParameters) { + return cpsAdminPersistenceService.queryCmHandles(cmHandleQueryParameters); + } } diff --git a/cps-service/src/main/java/org/onap/cps/api/impl/CpsDataServiceImpl.java b/cps-service/src/main/java/org/onap/cps/api/impl/CpsDataServiceImpl.java index aae355d507..2f1067aafe 100755 --- a/cps-service/src/main/java/org/onap/cps/api/impl/CpsDataServiceImpl.java +++ b/cps-service/src/main/java/org/onap/cps/api/impl/CpsDataServiceImpl.java @@ -36,6 +36,7 @@ import org.onap.cps.spi.exceptions.DataValidationException; import org.onap.cps.spi.model.Anchor; import org.onap.cps.spi.model.DataNode; import org.onap.cps.spi.model.DataNodeBuilder; +import org.onap.cps.utils.CpsValidator; import org.onap.cps.utils.YangUtils; import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; import org.opendaylight.yangtools.yang.model.api.SchemaContext; @@ -47,6 +48,7 @@ import org.springframework.stereotype.Service; public class CpsDataServiceImpl implements CpsDataService { private static final String ROOT_NODE_XPATH = "/"; + private static final long DEFAULT_LOCK_TIMEOUT_IN_MILLISECONDS = 300L; private final CpsDataPersistenceService cpsDataPersistenceService; private final CpsAdminService cpsAdminService; @@ -56,7 +58,8 @@ public class CpsDataServiceImpl implements CpsDataService { @Override public void saveData(final String dataspaceName, final String anchorName, final String jsonData, final OffsetDateTime observedTimestamp) { - final var dataNode = buildDataNode(dataspaceName, anchorName, ROOT_NODE_XPATH, jsonData); + CpsValidator.validateNameCharacters(dataspaceName, anchorName); + final DataNode dataNode = buildDataNode(dataspaceName, anchorName, ROOT_NODE_XPATH, jsonData); cpsDataPersistenceService.storeDataNode(dataspaceName, anchorName, dataNode); processDataUpdatedEventAsync(dataspaceName, anchorName, observedTimestamp, ROOT_NODE_XPATH, Operation.CREATE); } @@ -64,7 +67,8 @@ public class CpsDataServiceImpl implements CpsDataService { @Override public void saveData(final String dataspaceName, final String anchorName, final String parentNodeXpath, final String jsonData, final OffsetDateTime observedTimestamp) { - final var dataNode = buildDataNode(dataspaceName, anchorName, parentNodeXpath, jsonData); + CpsValidator.validateNameCharacters(dataspaceName, anchorName); + final DataNode dataNode = buildDataNode(dataspaceName, anchorName, parentNodeXpath, jsonData); cpsDataPersistenceService.addChildDataNode(dataspaceName, anchorName, parentNodeXpath, dataNode); processDataUpdatedEventAsync(dataspaceName, anchorName, observedTimestamp, parentNodeXpath, Operation.CREATE); } @@ -72,6 +76,7 @@ public class CpsDataServiceImpl implements CpsDataService { @Override public void saveListElements(final String dataspaceName, final String anchorName, final String parentNodeXpath, final String jsonData, final OffsetDateTime observedTimestamp) { + CpsValidator.validateNameCharacters(dataspaceName, anchorName); final Collection<DataNode> listElementDataNodeCollection = buildDataNodes(dataspaceName, anchorName, parentNodeXpath, jsonData); cpsDataPersistenceService.addListElements(dataspaceName, anchorName, parentNodeXpath, @@ -82,13 +87,15 @@ public class CpsDataServiceImpl implements CpsDataService { @Override public DataNode getDataNode(final String dataspaceName, final String anchorName, final String xpath, final FetchDescendantsOption fetchDescendantsOption) { + CpsValidator.validateNameCharacters(dataspaceName, anchorName); return cpsDataPersistenceService.getDataNode(dataspaceName, anchorName, xpath, fetchDescendantsOption); } @Override public void updateNodeLeaves(final String dataspaceName, final String anchorName, final String parentNodeXpath, final String jsonData, final OffsetDateTime observedTimestamp) { - final var dataNode = buildDataNode(dataspaceName, anchorName, parentNodeXpath, jsonData); + CpsValidator.validateNameCharacters(dataspaceName, anchorName); + final DataNode dataNode = buildDataNode(dataspaceName, anchorName, parentNodeXpath, jsonData); cpsDataPersistenceService .updateDataLeaves(dataspaceName, anchorName, dataNode.getXpath(), dataNode.getLeaves()); processDataUpdatedEventAsync(dataspaceName, anchorName, observedTimestamp, parentNodeXpath, Operation.UPDATE); @@ -99,6 +106,7 @@ public class CpsDataServiceImpl implements CpsDataService { final String parentNodeXpath, final String dataNodeUpdatesAsJson, final OffsetDateTime observedTimestamp) { + CpsValidator.validateNameCharacters(dataspaceName, anchorName); final Collection<DataNode> dataNodeUpdates = buildDataNodes(dataspaceName, anchorName, parentNodeXpath, dataNodeUpdatesAsJson); @@ -109,9 +117,31 @@ public class CpsDataServiceImpl implements CpsDataService { } @Override + public String startSession() { + return cpsDataPersistenceService.startSession(); + } + + @Override + public void closeSession(final String sessionId) { + cpsDataPersistenceService.closeSession(sessionId); + } + + @Override + public void lockAnchor(final String sessionID, final String dataspaceName, final String anchorName) { + lockAnchor(sessionID, dataspaceName, anchorName, DEFAULT_LOCK_TIMEOUT_IN_MILLISECONDS); + } + + @Override + public void lockAnchor(final String sessionID, final String dataspaceName, + final String anchorName, final Long timeoutInMilliseconds) { + cpsDataPersistenceService.lockAnchor(sessionID, dataspaceName, anchorName, timeoutInMilliseconds); + } + + @Override public void replaceNodeTree(final String dataspaceName, final String anchorName, final String parentNodeXpath, final String jsonData, final OffsetDateTime observedTimestamp) { - final var dataNode = buildDataNode(dataspaceName, anchorName, parentNodeXpath, jsonData); + CpsValidator.validateNameCharacters(dataspaceName, anchorName); + final DataNode dataNode = buildDataNode(dataspaceName, anchorName, parentNodeXpath, jsonData); cpsDataPersistenceService.replaceDataNodeTree(dataspaceName, anchorName, dataNode); processDataUpdatedEventAsync(dataspaceName, anchorName, observedTimestamp, parentNodeXpath, Operation.UPDATE); } @@ -119,6 +149,7 @@ public class CpsDataServiceImpl implements CpsDataService { @Override public void replaceListContent(final String dataspaceName, final String anchorName, final String parentNodeXpath, final String jsonData, final OffsetDateTime observedTimestamp) { + CpsValidator.validateNameCharacters(dataspaceName, anchorName); final Collection<DataNode> newListElements = buildDataNodes(dataspaceName, anchorName, parentNodeXpath, jsonData); replaceListContent(dataspaceName, anchorName, parentNodeXpath, newListElements, observedTimestamp); @@ -127,6 +158,7 @@ public class CpsDataServiceImpl implements CpsDataService { @Override public void replaceListContent(final String dataspaceName, final String anchorName, final String parentNodeXpath, final Collection<DataNode> dataNodes, final OffsetDateTime observedTimestamp) { + CpsValidator.validateNameCharacters(dataspaceName, anchorName); cpsDataPersistenceService.replaceListContent(dataspaceName, anchorName, parentNodeXpath, dataNodes); processDataUpdatedEventAsync(dataspaceName, anchorName, observedTimestamp, parentNodeXpath, Operation.UPDATE); } @@ -134,6 +166,7 @@ public class CpsDataServiceImpl implements CpsDataService { @Override public void deleteDataNode(final String dataspaceName, final String anchorName, final String dataNodeXpath, final OffsetDateTime observedTimestamp) { + CpsValidator.validateNameCharacters(dataspaceName, anchorName); cpsDataPersistenceService.deleteDataNode(dataspaceName, anchorName, dataNodeXpath); processDataUpdatedEventAsync(dataspaceName, anchorName, observedTimestamp, dataNodeXpath, Operation.DELETE); } @@ -141,7 +174,8 @@ public class CpsDataServiceImpl implements CpsDataService { @Override public void deleteDataNodes(final String dataspaceName, final String anchorName, final OffsetDateTime observedTimestamp) { - final var anchor = cpsAdminService.getAnchor(dataspaceName, anchorName); + CpsValidator.validateNameCharacters(dataspaceName, anchorName); + final Anchor anchor = cpsAdminService.getAnchor(dataspaceName, anchorName); cpsDataPersistenceService.deleteDataNodes(dataspaceName, anchorName); processDataUpdatedEventAsync(anchor, ROOT_NODE_XPATH, Operation.DELETE, observedTimestamp); } @@ -149,6 +183,7 @@ public class CpsDataServiceImpl implements CpsDataService { @Override public void deleteListOrListElement(final String dataspaceName, final String anchorName, final String listNodeXpath, final OffsetDateTime observedTimestamp) { + CpsValidator.validateNameCharacters(dataspaceName, anchorName); cpsDataPersistenceService.deleteListDataNode(dataspaceName, anchorName, listNodeXpath); processDataUpdatedEventAsync(dataspaceName, anchorName, observedTimestamp, listNodeXpath, Operation.DELETE); } @@ -156,8 +191,8 @@ public class CpsDataServiceImpl implements CpsDataService { private DataNode buildDataNode(final String dataspaceName, final String anchorName, final String parentNodeXpath, final String jsonData) { - final var anchor = cpsAdminService.getAnchor(dataspaceName, anchorName); - final var schemaContext = getSchemaContext(dataspaceName, anchor.getSchemaSetName()); + final Anchor anchor = cpsAdminService.getAnchor(dataspaceName, anchorName); + final SchemaContext schemaContext = getSchemaContext(dataspaceName, anchor.getSchemaSetName()); if (ROOT_NODE_XPATH.equals(parentNodeXpath)) { final NormalizedNode<?, ?> normalizedNode = YangUtils.parseJsonData(jsonData, schemaContext); @@ -176,8 +211,8 @@ public class CpsDataServiceImpl implements CpsDataService { final String parentNodeXpath, final String jsonData) { - final var anchor = cpsAdminService.getAnchor(dataspaceName, anchorName); - final var schemaContext = getSchemaContext(dataspaceName, anchor.getSchemaSetName()); + final Anchor anchor = cpsAdminService.getAnchor(dataspaceName, anchorName); + final SchemaContext schemaContext = getSchemaContext(dataspaceName, anchor.getSchemaSetName()); final NormalizedNode<?, ?> normalizedNode = YangUtils.parseJsonData(jsonData, schemaContext, parentNodeXpath); final Collection<DataNode> dataNodes = new DataNodeBuilder() @@ -194,7 +229,7 @@ public class CpsDataServiceImpl implements CpsDataService { private void processDataUpdatedEventAsync(final String dataspaceName, final String anchorName, final OffsetDateTime observedTimestamp, final String xpath, final Operation operation) { - final var anchor = cpsAdminService.getAnchor(dataspaceName, anchorName); + final Anchor anchor = cpsAdminService.getAnchor(dataspaceName, anchorName); this.processDataUpdatedEventAsync(anchor, xpath, operation, observedTimestamp); } diff --git a/cps-service/src/main/java/org/onap/cps/api/impl/CpsModuleServiceImpl.java b/cps-service/src/main/java/org/onap/cps/api/impl/CpsModuleServiceImpl.java index f0e79c60c7..db8a81f276 100644 --- a/cps-service/src/main/java/org/onap/cps/api/impl/CpsModuleServiceImpl.java +++ b/cps-service/src/main/java/org/onap/cps/api/impl/CpsModuleServiceImpl.java @@ -33,6 +33,7 @@ import org.onap.cps.spi.exceptions.SchemaSetInUseException; import org.onap.cps.spi.model.Anchor; import org.onap.cps.spi.model.ModuleReference; import org.onap.cps.spi.model.SchemaSet; +import org.onap.cps.utils.CpsValidator; import org.onap.cps.yang.YangTextSchemaSourceSetBuilder; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -48,6 +49,7 @@ public class CpsModuleServiceImpl implements CpsModuleService { @Override public void createSchemaSet(final String dataspaceName, final String schemaSetName, final Map<String, String> yangResourcesNameToContentMap) { + CpsValidator.validateNameCharacters(dataspaceName, schemaSetName); final var yangTextSchemaSourceSet = YangTextSchemaSourceSetBuilder.of(yangResourcesNameToContentMap); cpsModulePersistenceService.storeSchemaSet(dataspaceName, schemaSetName, yangResourcesNameToContentMap); @@ -58,6 +60,7 @@ public class CpsModuleServiceImpl implements CpsModuleService { public void createSchemaSetFromModules(final String dataspaceName, final String schemaSetName, final Map<String, String> newModuleNameToContentMap, final Collection<ModuleReference> moduleReferences) { + CpsValidator.validateNameCharacters(dataspaceName, schemaSetName); cpsModulePersistenceService.storeSchemaSetFromModules(dataspaceName, schemaSetName, newModuleNameToContentMap, moduleReferences); @@ -65,6 +68,7 @@ public class CpsModuleServiceImpl implements CpsModuleService { @Override public SchemaSet getSchemaSet(final String dataspaceName, final String schemaSetName) { + CpsValidator.validateNameCharacters(dataspaceName, schemaSetName); final var yangTextSchemaSourceSet = yangTextSchemaSourceSetCache .get(dataspaceName, schemaSetName); return SchemaSet.builder().name(schemaSetName).dataspaceName(dataspaceName) @@ -75,6 +79,7 @@ public class CpsModuleServiceImpl implements CpsModuleService { @Transactional public void deleteSchemaSet(final String dataspaceName, final String schemaSetName, final CascadeDeleteAllowed cascadeDeleteAllowed) { + CpsValidator.validateNameCharacters(dataspaceName, schemaSetName); final Collection<Anchor> anchors = cpsAdminService.getAnchors(dataspaceName, schemaSetName); if (!anchors.isEmpty() && isCascadeDeleteProhibited(cascadeDeleteAllowed)) { throw new SchemaSetInUseException(dataspaceName, schemaSetName); @@ -89,23 +94,25 @@ public class CpsModuleServiceImpl implements CpsModuleService { @Override public Collection<ModuleReference> getYangResourceModuleReferences(final String dataspaceName) { + CpsValidator.validateNameCharacters(dataspaceName); return cpsModulePersistenceService.getYangResourceModuleReferences(dataspaceName); } @Override public Collection<ModuleReference> getYangResourcesModuleReferences(final String dataspaceName, final String anchorName) { + CpsValidator.validateNameCharacters(dataspaceName, anchorName); return cpsModulePersistenceService.getYangResourceModuleReferences(dataspaceName, anchorName); } - private boolean isCascadeDeleteProhibited(final CascadeDeleteAllowed cascadeDeleteAllowed) { - return CascadeDeleteAllowed.CASCADE_DELETE_PROHIBITED == cascadeDeleteAllowed; - } - @Override public Collection<ModuleReference> identifyNewModuleReferences( final Collection<ModuleReference> moduleReferencesToCheck) { return cpsModulePersistenceService.identifyNewModuleReferences(moduleReferencesToCheck); } + private boolean isCascadeDeleteProhibited(final CascadeDeleteAllowed cascadeDeleteAllowed) { + return CascadeDeleteAllowed.CASCADE_DELETE_PROHIBITED == cascadeDeleteAllowed; + } + } diff --git a/cps-service/src/main/java/org/onap/cps/api/impl/CpsQueryServiceImpl.java b/cps-service/src/main/java/org/onap/cps/api/impl/CpsQueryServiceImpl.java index dd9f160dbf..c2003d6bf7 100644 --- a/cps-service/src/main/java/org/onap/cps/api/impl/CpsQueryServiceImpl.java +++ b/cps-service/src/main/java/org/onap/cps/api/impl/CpsQueryServiceImpl.java @@ -25,6 +25,7 @@ import org.onap.cps.api.CpsQueryService; import org.onap.cps.spi.CpsDataPersistenceService; import org.onap.cps.spi.FetchDescendantsOption; import org.onap.cps.spi.model.DataNode; +import org.onap.cps.utils.CpsValidator; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -37,6 +38,7 @@ public class CpsQueryServiceImpl implements CpsQueryService { @Override public Collection<DataNode> queryDataNodes(final String dataspaceName, final String anchorName, final String cpsPath, final FetchDescendantsOption fetchDescendantsOption) { + CpsValidator.validateNameCharacters(dataspaceName, anchorName); return cpsDataPersistenceService.queryDataNodes(dataspaceName, anchorName, cpsPath, fetchDescendantsOption); } } diff --git a/cps-service/src/main/java/org/onap/cps/api/impl/YangTextSchemaSourceSetCache.java b/cps-service/src/main/java/org/onap/cps/api/impl/YangTextSchemaSourceSetCache.java index 03b52a3088..fb881a97b6 100644 --- a/cps-service/src/main/java/org/onap/cps/api/impl/YangTextSchemaSourceSetCache.java +++ b/cps-service/src/main/java/org/onap/cps/api/impl/YangTextSchemaSourceSetCache.java @@ -24,6 +24,7 @@ package org.onap.cps.api.impl; import com.google.errorprone.annotations.CanIgnoreReturnValue; import java.util.Map; import org.onap.cps.spi.CpsModulePersistenceService; +import org.onap.cps.utils.CpsValidator; import org.onap.cps.yang.YangTextSchemaSourceSet; import org.onap.cps.yang.YangTextSchemaSourceSetBuilder; import org.springframework.beans.factory.annotation.Autowired; @@ -52,6 +53,7 @@ public class YangTextSchemaSourceSetCache { */ @Cacheable(key = "#p0.concat('-').concat(#p1)") public YangTextSchemaSourceSet get(final String dataspaceName, final String schemaSetName) { + CpsValidator.validateNameCharacters(dataspaceName, schemaSetName); final Map<String, String> yangResourceNameToContent = cpsModulePersistenceService.getYangSchemaResources(dataspaceName, schemaSetName); return YangTextSchemaSourceSetBuilder.of(yangResourceNameToContent); @@ -69,6 +71,7 @@ public class YangTextSchemaSourceSetCache { @CanIgnoreReturnValue public YangTextSchemaSourceSet updateCache(final String dataspaceName, final String schemaSetName, final YangTextSchemaSourceSet yangTextSchemaSourceSet) { + CpsValidator.validateNameCharacters(dataspaceName, schemaSetName); return yangTextSchemaSourceSet; } @@ -81,6 +84,7 @@ public class YangTextSchemaSourceSetCache { */ @CacheEvict(key = "#p0.concat('-').concat(#p1)") public void removeFromCache(final String dataspaceName, final String schemaSetName) { + CpsValidator.validateNameCharacters(dataspaceName, schemaSetName); // Spring provides implementation for removing object from cache } diff --git a/cps-service/src/main/java/org/onap/cps/spi/CpsAdminPersistenceService.java b/cps-service/src/main/java/org/onap/cps/spi/CpsAdminPersistenceService.java index dd4059d88c..25167e844a 100755 --- a/cps-service/src/main/java/org/onap/cps/spi/CpsAdminPersistenceService.java +++ b/cps-service/src/main/java/org/onap/cps/spi/CpsAdminPersistenceService.java @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2020 Nordix Foundation. + * Copyright (C) 2020-2022 Nordix Foundation. * Modifications Copyright (C) 2020-2022 Bell Canada. * Modifications Copyright (C) 2021 Pantheon.tech * ================================================================================ @@ -23,8 +23,10 @@ package org.onap.cps.spi; import java.util.Collection; +import java.util.Set; import org.onap.cps.spi.exceptions.AlreadyDefinedException; import org.onap.cps.spi.model.Anchor; +import org.onap.cps.spi.model.CmHandleQueryParameters; /* Service for handling CPS admin data. @@ -99,4 +101,12 @@ public interface CpsAdminPersistenceService { * @param anchorName anchor name */ void deleteAnchor(String dataspaceName, String anchorName); + + /** + * Query and return cm handles that match the given query parameters. + * + * @param cmHandleQueryParameters the cm handle query parameters + * @return collection of cm handle ids + */ + Set<String> queryCmHandles(CmHandleQueryParameters cmHandleQueryParameters); } diff --git a/cps-service/src/main/java/org/onap/cps/spi/CpsDataPersistenceService.java b/cps-service/src/main/java/org/onap/cps/spi/CpsDataPersistenceService.java index fd658861c2..43cfffee70 100644 --- a/cps-service/src/main/java/org/onap/cps/spi/CpsDataPersistenceService.java +++ b/cps-service/src/main/java/org/onap/cps/spi/CpsDataPersistenceService.java @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2020 Nordix Foundation. + * Copyright (C) 2020-2022 Nordix Foundation. * Modifications Copyright (C) 2021 Pantheon.tech * Modifications Copyright (C) 2022 Bell Canada * ================================================================================ @@ -148,4 +148,29 @@ public interface CpsDataPersistenceService { Collection<DataNode> queryDataNodes(String dataspaceName, String anchorName, String cpsPath, FetchDescendantsOption fetchDescendantsOption); + /** + * Starts a session which allows use of locks and batch interaction with the persistence service. + * + * @return Session ID string + */ + String startSession(); + + /** + * Close session. + * + * @param sessionId session ID + */ + void closeSession(String sessionId); + + /** + * Lock anchor. + * To release locks(s), the session holding the lock(s) must be closed. + * + * @param sessionID session ID + * @param dataspaceName dataspace name + * @param anchorName anchor name + * @param timeoutInMilliseconds lock attempt timeout in milliseconds + */ + void lockAnchor(String sessionID, String dataspaceName, String anchorName, Long timeoutInMilliseconds); + } diff --git a/cps-service/src/main/java/org/onap/cps/spi/exceptions/SessionManagerException.java b/cps-service/src/main/java/org/onap/cps/spi/exceptions/SessionManagerException.java new file mode 100644 index 0000000000..4000bfc51d --- /dev/null +++ b/cps-service/src/main/java/org/onap/cps/spi/exceptions/SessionManagerException.java @@ -0,0 +1,48 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2022 Nordix Foundation + * ================================================================================ + * 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. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.cps.spi.exceptions; + + +public class SessionManagerException extends CpsException { + + private static final long serialVersionUID = 7957090904519019500L; + + /** + * Constructor. + * + * @param message the error message + * @param details the error details + * @param cause the cause of the exception + */ + public SessionManagerException(final String message, final String details, final Throwable cause) { + super(message, details, cause); + } + + /** + * Constructor. + * + * @param message the error message + * @param details the error details + */ + public SessionManagerException(final String message, final String details) { + super(message, details); + } +} diff --git a/cps-service/src/main/java/org/onap/cps/spi/exceptions/SessionTimeoutException.java b/cps-service/src/main/java/org/onap/cps/spi/exceptions/SessionTimeoutException.java new file mode 100644 index 0000000000..92b4aa7a8b --- /dev/null +++ b/cps-service/src/main/java/org/onap/cps/spi/exceptions/SessionTimeoutException.java @@ -0,0 +1,31 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2022 Nordix Foundation + * ================================================================================ + * 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. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.cps.spi.exceptions; + +@SuppressWarnings("squid:S110") // Team agreed to accept 6 levels of inheritance for CPS Exceptions +public class SessionTimeoutException extends SessionManagerException { + + private static final long serialVersionUID = -8809577494038691360L; + + public SessionTimeoutException(final String message, final String details, final Throwable cause) { + super(message, details, cause); + } +} diff --git a/cps-service/src/main/java/org/onap/cps/spi/model/CmHandleQueryParameters.java b/cps-service/src/main/java/org/onap/cps/spi/model/CmHandleQueryParameters.java new file mode 100644 index 0000000000..ff4e627636 --- /dev/null +++ b/cps-service/src/main/java/org/onap/cps/spi/model/CmHandleQueryParameters.java @@ -0,0 +1,41 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2022 Nordix Foundation + * ================================================================================ + * 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. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.cps.spi.model; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonInclude.Include; +import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.Collections; +import java.util.Map; +import javax.validation.Valid; +import lombok.Getter; +import lombok.Setter; + +@Setter +@Getter +@JsonInclude(Include.NON_NULL) +public class CmHandleQueryParameters { + + @JsonProperty("publicCmHandleProperties") + @Valid + private Map<String, String> publicProperties = Collections.emptyMap(); + +} diff --git a/cps-service/src/main/java/org/onap/cps/spi/model/DataNode.java b/cps-service/src/main/java/org/onap/cps/spi/model/DataNode.java index 55e7b9970b..43aa06b81b 100644 --- a/cps-service/src/main/java/org/onap/cps/spi/model/DataNode.java +++ b/cps-service/src/main/java/org/onap/cps/spi/model/DataNode.java @@ -26,11 +26,13 @@ import java.util.Collection; import java.util.Collections; import java.util.Map; import lombok.AccessLevel; +import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.Setter; @Setter(AccessLevel.PROTECTED) @Getter +@EqualsAndHashCode public class DataNode { DataNode() { } diff --git a/cps-service/src/main/java/org/onap/cps/utils/CpsValidator.java b/cps-service/src/main/java/org/onap/cps/utils/CpsValidator.java new file mode 100644 index 0000000000..28b49c9666 --- /dev/null +++ b/cps-service/src/main/java/org/onap/cps/utils/CpsValidator.java @@ -0,0 +1,62 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2022 Nordix Foundation + * ================================================================================ + * 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. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.cps.utils; + +import com.google.common.collect.Lists; +import java.util.Collection; +import java.util.regex.Pattern; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.onap.cps.spi.exceptions.DataValidationException; + +@Slf4j +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public final class CpsValidator { + + private static final char[] UNSUPPORTED_NAME_CHARACTERS = "!\" #$%&'()*+,./\\:;<=>?@[]^`{|}~".toCharArray(); + private static final Pattern TOPIC_NAME_PATTERN = Pattern.compile("^[a-zA-Z0-9]([._-](?![._-])|" + + "[a-zA-Z0-9]){0,120}[a-zA-Z0-9]$"); + + /** + * Validate characters in names within cps. + * @param names names of data to be validated + */ + public static void validateNameCharacters(final String... names) { + for (final String name : names) { + final Collection<Character> charactersOfName = Lists.charactersOf(name); + for (final char unsupportedCharacter : UNSUPPORTED_NAME_CHARACTERS) { + if (charactersOfName.contains(unsupportedCharacter)) { + throw new DataValidationException("Name or ID Validation Error.", + name + " invalid token encountered at position " + (name.indexOf(unsupportedCharacter) + 1)); + } + } + } + } + + /** + * Validate kafka topic name pattern. + * @param topicName name of the topic to be validated + */ + public static boolean validateTopicName(final String topicName) { + return topicName != null && TOPIC_NAME_PATTERN.matcher(topicName).matches(); + } +} |