2 * Copyright 2019 Huawei Technologies Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 package org.onap.cli.fw.store;
20 import java.io.IOException;
21 import java.nio.charset.Charset;
22 import java.nio.file.Files;
23 import java.nio.file.Paths;
24 import java.security.MessageDigest;
25 import java.security.NoSuchAlgorithmException;
26 import java.text.SimpleDateFormat;
27 import java.util.ArrayList;
28 import java.util.Date;
29 import java.util.HashMap;
30 import java.util.List;
31 import java.util.Locale;
33 import java.util.TimeZone;
35 import javax.xml.bind.DatatypeConverter;
37 import org.apache.commons.io.FileUtils;
38 import org.onap.cli.fw.conf.OnapCommandConfig;
39 import org.onap.cli.fw.conf.OnapCommandConstants;
40 import org.onap.cli.fw.error.OnapCommandArtifactAlreadyExist;
41 import org.onap.cli.fw.error.OnapCommandArtifactContentChecksumNotMatch;
42 import org.onap.cli.fw.error.OnapCommandArtifactContentNotExist;
43 import org.onap.cli.fw.error.OnapCommandArtifactNotFound;
44 import org.slf4j.Logger;
45 import org.slf4j.LoggerFactory;
47 import com.google.gson.Gson;
48 import com.google.gson.GsonBuilder;
49 import com.google.gson.stream.JsonReader;
50 import java.io.FileReader;
52 public class OnapCommandArtifactStore {
53 private static Logger log = LoggerFactory.getLogger(OnapCommandArtifactStore.class);
54 private static Gson gson = new GsonBuilder().serializeNulls().create();
56 private static boolean storeReady = false; //NOSONAR
58 private SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS", Locale.US);
60 private static final String SEPARATOR = "__";
62 public static class Artifact {
64 private String description;
65 private String categoty;
66 private String checksum;
68 private String createAt;
69 private String lastUpdatedAt;
71 private Map<String, String> metadata = new HashMap<>();
72 public String getName() {
75 public void setName(String name) {
78 public String getChecksum() {
81 public void setChecksum(String checksum) {
82 this.checksum = checksum;
85 public String getDescription() {
88 public void setDescription(String description) {
89 this.description = description;
91 public String getCategoty() {
94 public void setCategoty(String categoty) {
95 this.categoty = categoty;
98 public long getSize() {
101 public void setSize(long l) {
104 public String getCreateAt() {
107 public void setCreateAt(String createAt) {
108 this.createAt = createAt;
110 public String getLastUpdatedAt() {
111 return lastUpdatedAt;
113 public void setLastUpdatedAt(String lastUpdatedAt) {
114 this.lastUpdatedAt = lastUpdatedAt;
116 public String getPath() {
119 public void setPath(String path) {
122 public Map<String, String> getMetadata() {
125 public void setMetadata(Map<String, String> metadata) {
126 this.metadata = metadata;
132 FileUtils.forceMkdir(new File(getBasePath()));
134 } catch (IOException e) {
135 log.error("Failed to create the data store results");
139 private static OnapCommandArtifactStore store = null;
141 private OnapCommandArtifactStore() {
142 this.dateFormatter.setTimeZone(TimeZone.getTimeZone("UTC"));
145 public static OnapCommandArtifactStore getStore() {
147 store = new OnapCommandArtifactStore();
153 private static String getBasePath() {
154 return OnapCommandConfig.getPropertyValue(OnapCommandConstants.OPEN_CLI_DATA_DIR) +
155 File.separator + "artifacts";
158 private static String getArtifactPath(String name, String category) {
159 return getBasePath() + File.separator + name + SEPARATOR + category + ".json";
162 private String getChecksum(String storePath) throws IOException, NoSuchAlgorithmException {
163 byte[] b = Files.readAllBytes(Paths.get(storePath));
164 byte[] hash = MessageDigest.getInstance("MD5").digest(b); //NOSONAR
165 return DatatypeConverter.printHexBinary(hash);
168 public Artifact createArtifact(Artifact artifact) throws OnapCommandArtifactContentNotExist, OnapCommandArtifactAlreadyExist, OnapCommandArtifactContentChecksumNotMatch { //NOSONAR
169 if (!new File(artifact.getPath()).exists()) {
170 throw new OnapCommandArtifactContentNotExist(artifact.getPath());
173 String storePath = getArtifactPath(artifact.getName(), artifact.getCategoty());
174 File aFile = new File(storePath);
175 if (aFile.exists()) {
176 throw new OnapCommandArtifactAlreadyExist(artifact.getName(), artifact.getCategoty());
180 String actual = this.getChecksum(artifact.getPath());
181 artifact.setChecksum(actual);
183 artifact.setSize(new File(artifact.getPath()).length() / 1024);
185 artifact.setCreateAt(dateFormatter.format(new Date()));
186 artifact.setLastUpdatedAt(artifact.getCreateAt());
188 FileUtils.writeStringToFile(new File(storePath), gson.toJson(artifact), (Charset) null);
189 } catch (Exception e) { // NOSONAR
190 //It is expected that this never occurs
191 log.error("Failed to store the artifact at {}", storePath);
197 public Artifact getArtifact(String name, String category) throws OnapCommandArtifactNotFound {
198 String storePath = getArtifactPath(name, category);
199 File aFile = new File(storePath);
200 if (!aFile.exists()) {
201 throw new OnapCommandArtifactNotFound(name, category);
205 return gson.fromJson(FileUtils.readFileToString(aFile, (Charset) null), Artifact.class);
206 } catch (Exception e) { // NOSONAR
207 //It is expected that this never occurs
208 log.error("Failed to retrieve the artifact at {}", storePath);
214 public List<Artifact> listArtifact(String category, String namePattern) throws OnapCommandArtifactNotFound { //NOSONAR
215 List<Artifact> artifacts = new ArrayList<>();
217 String searchPattern = "";
218 if (namePattern != null && !namePattern.isEmpty()) {
219 searchPattern += namePattern;
221 searchPattern += "*";
224 searchPattern += SEPARATOR;
226 if (category != null && !category.isEmpty()) {
227 searchPattern += category;
229 searchPattern += "*";
232 searchPattern += ".json";
234 final String SP = searchPattern; //NOSONAR
236 for (File file: new File(getBasePath()).listFiles()) {
237 try (JsonReader jsonReader = new JsonReader(new FileReader(file))){
238 artifacts.add(gson.fromJson(jsonReader, Artifact.class));
239 } catch (Exception e) { // NOSONAR
240 //It is expected that this never occurs
241 String fileAbsPath = file.getAbsolutePath();
242 log.error("While seraching Failed to retrieve the artifact at {}", fileAbsPath);
249 public void deleteArtifact(String name, String category) throws OnapCommandArtifactNotFound {
250 String storePath = getArtifactPath(name, category);
251 File aFile = new File(storePath);
252 if (!aFile.exists()) {
253 throw new OnapCommandArtifactNotFound(name, category);
256 Files.delete(Paths.get(storePath));
257 } catch (IOException e) {
258 log.error("Failed to delete the artifact {}", aFile.getAbsolutePath());
262 public Artifact setArtifact(Artifact artifact, Artifact existing) throws OnapCommandArtifactNotFound, OnapCommandArtifactContentNotExist, OnapCommandArtifactAlreadyExist, IOException, NoSuchAlgorithmException {
263 if (artifact.getName() == null) {
264 artifact.setName(existing.getName());
267 if (artifact.getDescription() == null) {
268 artifact.setDescription(existing.getDescription());
271 if (artifact.getCategoty() == null) {
272 artifact.setCategoty(existing.getCategoty());
275 if (artifact.getPath()!= null) {
276 if (!new File(artifact.getPath()).exists()) {
277 throw new OnapCommandArtifactContentNotExist(artifact.getPath());
279 String actual = this.getChecksum(artifact.getPath());
280 if (!existing.getChecksum().equals(actual)) {
281 artifact.setChecksum(actual);
282 artifact.setSize(new File(artifact.getPath()).length() / 1024);
285 artifact.setPath(existing.getPath());
288 artifact.setCreateAt(existing.getCreateAt());
289 artifact.setLastUpdatedAt(dateFormatter.format(new Date()));
293 public Artifact updateArtifact(String name, String category, Artifact artifact) throws OnapCommandArtifactNotFound, OnapCommandArtifactContentNotExist, OnapCommandArtifactAlreadyExist {
294 Artifact existing = this.getArtifact(name, category);
295 String existingStorePath = getArtifactPath(name, category);
297 String newStorePath = getArtifactPath(artifact.getName(), artifact.getCategoty());
298 if ( !existingStorePath.equalsIgnoreCase(newStorePath) && new File(newStorePath).exists()) {
299 throw new OnapCommandArtifactAlreadyExist(artifact.getName(), artifact.getCategoty());
303 artifact = setArtifact(artifact, existing);
304 if (artifact.getMetadata().size() > 0) {
305 //update to existing one
306 for (Map.Entry<String, String> entry: artifact.getMetadata().entrySet()) {
307 if (entry.getValue() == null || entry.getValue().isEmpty() || entry.getValue().equalsIgnoreCase("null")) {
308 existing.getMetadata().remove(entry.getKey());
310 existing.getMetadata().put(entry.getKey(), entry.getValue());
313 artifact.setMetadata(existing.getMetadata());
316 FileUtils.writeStringToFile(new File(newStorePath), gson.toJson(artifact), (Charset) null);
318 if (!newStorePath.equalsIgnoreCase(existingStorePath)) {
319 this.deleteArtifact(name, category);
321 } catch (Exception e) { // NOSONAR
322 //It is expected that this never occurs
323 log.error("Failed to update the artifact at {}", existingStorePath);