2 * ========================LICENSE_START=================================
4 * ======================================================================
5 * Copyright (C) 2019-2020 Nordix Foundation. All rights reserved.
6 * ======================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 * ========================LICENSE_END===================================
21 package org.onap.ccsdk.oran.a1policymanagementservice.repository;
23 import com.google.gson.Gson;
24 import com.google.gson.GsonBuilder;
27 import java.io.FileOutputStream;
28 import java.io.PrintStream;
29 import java.lang.invoke.MethodHandles;
30 import java.nio.file.Files;
31 import java.nio.file.Path;
32 import java.time.Instant;
33 import java.util.ArrayList;
34 import java.util.Collection;
35 import java.util.HashMap;
36 import java.util.List;
39 import java.util.Vector;
41 import lombok.Builder;
44 import org.onap.ccsdk.oran.a1policymanagementservice.configuration.ApplicationConfig;
45 import org.onap.ccsdk.oran.a1policymanagementservice.exceptions.EntityNotFoundException;
46 import org.onap.ccsdk.oran.a1policymanagementservice.exceptions.ServiceException;
47 import org.slf4j.Logger;
48 import org.slf4j.LoggerFactory;
49 import org.springframework.beans.factory.annotation.Autowired;
50 import org.springframework.context.annotation.Configuration;
51 import org.springframework.util.FileSystemUtils;
52 import reactor.util.annotation.Nullable;
54 @SuppressWarnings("squid:S2629") // Invoke method(s) only conditionally
56 public class Policies {
60 private static class PersistentPolicyInfo {
63 private String ownerServiceId;
65 private String typeId;
66 private String statusNotificationUri;
67 private boolean isTransient;
68 private String lastModified;
71 private final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
72 private Map<String, Policy> policiesId = new HashMap<>();
73 private MultiMap<Policy> policiesRic = new MultiMap<>();
74 private MultiMap<Policy> policiesService = new MultiMap<>();
75 private MultiMap<Policy> policiesType = new MultiMap<>();
77 private final ApplicationConfig appConfig;
78 private static Gson gson = new GsonBuilder().create();
80 public Policies(@Autowired ApplicationConfig appConfig) {
81 this.appConfig = appConfig;
84 public synchronized void put(Policy policy) {
85 policiesId.put(policy.getId(), policy);
86 policiesRic.put(policy.getRic().id(), policy.getId(), policy);
87 policiesService.put(policy.getOwnerServiceId(), policy.getId(), policy);
88 policiesType.put(policy.getType().getId(), policy.getId(), policy);
89 if (this.appConfig.getVardataDirectory() != null && !policy.isTransient()) {
94 public synchronized boolean containsPolicy(String id) {
95 return policiesId.containsKey(id);
98 public synchronized Policy get(String id) {
99 return policiesId.get(id);
102 public synchronized Policy getPolicy(String id) throws EntityNotFoundException {
103 Policy p = policiesId.get(id);
105 throw new EntityNotFoundException("Could not find policy: " + id);
110 public synchronized Collection<Policy> getAll() {
111 return new Vector<>(policiesId.values());
114 public synchronized Collection<Policy> getForService(String service) {
115 return policiesService.get(service);
118 public synchronized Collection<Policy> getForRic(String ric) {
119 return policiesRic.get(ric);
122 public synchronized Collection<Policy> getForType(String type) {
123 return policiesType.get(type);
126 public synchronized Policy removeId(String id) {
127 Policy p = policiesId.get(id);
134 public synchronized void remove(Policy policy) {
135 if (!policy.isTransient()) {
137 Files.delete(getPath(policy));
138 } catch (Exception e) {
139 logger.debug("Could not delete policy from database: {}", e.getMessage());
142 policiesId.remove(policy.getId());
143 policiesRic.remove(policy.getRic().id(), policy.getId());
144 policiesService.remove(policy.getOwnerServiceId(), policy.getId());
145 policiesType.remove(policy.getType().getId(), policy.getId());
148 public synchronized void removePoliciesForRic(String ricId) {
149 Collection<Policy> policiesForRic = getForRic(ricId);
150 for (Policy policy : policiesForRic) {
155 public Collection<Policy> filterPolicies(@Nullable String typeId, @Nullable String ricId,
156 @Nullable String serviceId, @Nullable String typeName) {
158 if (typeId != null) {
159 return filter(this.getForType(typeId), null, ricId, serviceId, typeName);
160 } else if (serviceId != null) {
161 return filter(this.getForService(serviceId), typeId, ricId, null, typeName);
162 } else if (ricId != null) {
163 return filter(this.getForRic(ricId), typeId, null, serviceId, typeName);
165 return filter(this.getAll(), typeId, ricId, serviceId, typeName);
169 public synchronized int size() {
170 return policiesId.size();
173 public synchronized void clear() {
174 while (policiesId.size() > 0) {
175 Set<String> keys = policiesId.keySet();
176 removeId(keys.iterator().next());
179 if (this.appConfig.getVardataDirectory() != null) {
180 FileSystemUtils.deleteRecursively(getDatabasePath());
182 } catch (Exception e) {
183 logger.warn("Could not delete policy database : {}", e.getMessage());
187 public void store(Policy policy) {
189 Files.createDirectories(getDatabasePath(policy.getRic()));
190 try (PrintStream out = new PrintStream(new FileOutputStream(getFile(policy)))) {
191 out.print(gson.toJson(toStorageObject(policy)));
193 } catch (Exception e) {
194 logger.warn("Could not store policy: {} {}", policy.getId(), e.getMessage());
198 private boolean isMatch(String filterValue, String actualValue) {
199 return filterValue == null || actualValue.equals(filterValue);
202 private boolean isTypeMatch(Policy policy, @Nullable String typeName) {
203 return (typeName == null) || policy.getType().getTypeId().getName().equals(typeName);
206 private Collection<Policy> filter(Collection<Policy> collection, String typeId, String ricId, String serviceId,
208 if (typeId == null && ricId == null && serviceId == null && typeName == null) {
211 List<Policy> filtered = new ArrayList<>(collection.size());
212 for (Policy p : collection) {
213 if (isMatch(typeId, p.getType().getId()) && isMatch(ricId, p.getRic().id())
214 && isMatch(serviceId, p.getOwnerServiceId()) && isTypeMatch(p, typeName)) {
221 private File getFile(Policy policy) throws ServiceException {
222 return getPath(policy).toFile();
225 private Path getPath(Policy policy) throws ServiceException {
226 return Path.of(getDatabaseDirectory(policy.getRic()), policy.getId() + ".json");
229 public synchronized void restoreFromDatabase(Ric ric, PolicyTypes types) {
231 Files.createDirectories(getDatabasePath(ric));
232 for (File file : getDatabasePath(ric).toFile().listFiles()) {
233 String json = Files.readString(file.toPath());
234 PersistentPolicyInfo policyStorage = gson.fromJson(json, PersistentPolicyInfo.class);
235 this.put(toPolicy(policyStorage, ric, types));
237 logger.debug("Restored policy database for RIC: {}, number of policies: {}", ric.id(),
238 this.policiesRic.get(ric.id()).size());
239 } catch (Exception e) {
240 logger.warn("Could not restore policy database for RIC: {}, reason : {}", ric.id(), e.getMessage());
244 private PersistentPolicyInfo toStorageObject(Policy p) {
245 return PersistentPolicyInfo.builder() //
247 .json(p.getJson()) //
248 .ownerServiceId(p.getOwnerServiceId()) //
249 .ricId(p.getRic().id()) //
250 .statusNotificationUri(p.getStatusNotificationUri()) //
251 .typeId(p.getType().getId()) //
252 .isTransient(p.isTransient()) //
253 .lastModified(p.getLastModified().toString()) //
257 Policy toPolicy(PersistentPolicyInfo p, Ric ric, PolicyTypes types) throws EntityNotFoundException {
258 return Policy.builder() //
260 .isTransient(p.isTransient()) //
261 .json(p.getJson()) //
262 .lastModified(Instant.parse(p.lastModified)) //
263 .ownerServiceId(p.getOwnerServiceId()) //
265 .statusNotificationUri(p.getStatusNotificationUri()) //
266 .type(types.getType(p.getTypeId())) //
270 private Path getDatabasePath(Ric ric) throws ServiceException {
271 return Path.of(getDatabaseDirectory(ric));
274 private String getDatabaseDirectory(Ric ric) throws ServiceException {
275 return getDatabaseDirectory() + "/" + ric.id();
278 private String getDatabaseDirectory() throws ServiceException {
279 if (appConfig.getVardataDirectory() == null) {
280 throw new ServiceException("No database storage provided");
282 return appConfig.getVardataDirectory() + "/database/policyInstances";
285 private Path getDatabasePath() throws ServiceException {
286 return Path.of(getDatabaseDirectory());