2 * ============LICENSE_START=======================================================
3 * Copyright (C) 2019 Nordix Foundation.
4 * ================================================================================
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
17 * SPDX-License-Identifier: Apache-2.0
18 * ============LICENSE_END=========================================================
21 package org.openecomp.sdc.tosca.csar;
23 import java.util.ArrayList;
24 import java.util.List;
25 import java.util.Map.Entry;
26 import java.util.Optional;
27 import org.apache.commons.lang.StringUtils;
28 import org.openecomp.sdc.common.errors.Messages;
31 * Processes a SOL004 Manifest.
33 public class SOL004ManifestOnboarding extends AbstractOnboardingManifest {
36 protected void processMetadata() {
37 Optional<String> currentLine = getCurrentLine();
38 //SOL004 #4.3.2: The manifest file shall start with the package metadata
39 if (!currentLine.isPresent() || !isMetadata(currentLine.get())) {
40 reportError(Messages.MANIFEST_START_METADATA);
41 continueToProcess = false;
44 while (continueToProcess) {
45 currentLine = readNextNonEmptyLine();
46 if (!currentLine.isPresent()) {
47 continueToProcess = validateMetadata();
50 final String metadataLine = currentLine.get();
51 final String metadataEntry = readEntryName(metadataLine).orElse(null);
52 if (!isMetadataEntry(metadataEntry)) {
53 if (metadata.size() < MAX_ALLOWED_MANIFEST_META_ENTRIES) {
54 reportError(Messages.MANIFEST_METADATA_INVALID_ENTRY1, metadataLine);
55 continueToProcess = false;
58 continueToProcess = validateMetadata();
61 final String metadataValue = readEntryValue(metadataLine).orElse(null);
62 addToMetadata(metadataEntry, metadataValue);
63 continueToProcess = isValid();
65 readNextNonEmptyLine();
69 protected void processBody() {
70 while (continueToProcess) {
71 final ManifestTokenType manifestTokenType = detectLineEntry().orElse(null);
72 if (manifestTokenType == null) {
73 getCurrentLine().ifPresent(line -> reportInvalidLine());
77 switch (manifestTokenType) {
81 case NON_MANO_ARTIFACT_SETS:
82 processNonManoArtifactEntry();
88 getCurrentLine().ifPresent(line -> reportInvalidLine());
89 continueToProcess = false;
96 * Processes the {@link ManifestTokenType#NON_MANO_ARTIFACT_SETS} entry.
98 private void processNonManoArtifactEntry() {
99 Optional<String> currentLine = readNextNonEmptyLine();
100 while (currentLine.isPresent()) {
101 final ManifestTokenType manifestTokenType = detectLineEntry().orElse(null);
102 if (manifestTokenType == ManifestTokenType.CMS_BEGIN) {
105 if (manifestTokenType != null) {
106 reportError(Messages.MANIFEST_INVALID_NON_MANO_KEY, manifestTokenType.getToken());
107 continueToProcess = false;
110 final String nonManoKey = readCurrentEntryName().orElse(null);
111 if (nonManoKey == null) {
112 reportError(Messages.MANIFEST_INVALID_NON_MANO_KEY, currentLine.get());
113 continueToProcess = false;
116 readNextNonEmptyLine();
117 final List<String> nonManoSourceList = readNonManoSourceList();
119 continueToProcess = false;
122 if (nonManoSourceList.isEmpty()) {
123 reportError(Messages.MANIFEST_EMPTY_NON_MANO_KEY, nonManoKey);
124 continueToProcess = false;
127 if (nonManoSources.get(nonManoKey) == null) {
128 nonManoSources.put(nonManoKey, nonManoSourceList);
130 nonManoSources.get(nonManoKey).addAll(nonManoSourceList);
132 currentLine = getCurrentLine();
137 * Processes {@link ManifestTokenType#SOURCE} entries in {@link ManifestTokenType#NON_MANO_ARTIFACT_SETS}.
139 * @return A list of sources paths
141 private List<String> readNonManoSourceList() {
142 final List<String> nonManoSourceList = new ArrayList<>();
143 while (getCurrentLine().isPresent()) {
144 final ManifestTokenType manifestTokenType = detectLineEntry().orElse(null);
145 if (manifestTokenType != ManifestTokenType.SOURCE) {
149 final String value = readCurrentEntryValue().orElse(null);
150 if (!StringUtils.isEmpty(value)) {
151 nonManoSourceList.add(value);
153 reportError(Messages.MANIFEST_EMPTY_NON_MANO_SOURCE);
157 readNextNonEmptyLine();
159 return nonManoSourceList;
163 * Reads a manifest CMS signature.
165 private void readCmsSignature() {
166 if (cmsSignature != null) {
167 reportError(Messages.MANIFEST_SIGNATURE_DUPLICATED);
168 continueToProcess = false;
171 final StringBuilder cmsSignatureBuilder = new StringBuilder();
173 cmsSignatureBuilder.append(currentLine).append("\n");
174 Optional<String> currentLine = readNextNonEmptyLine();
175 if(!getCurrentLine().isPresent()) {
178 while (currentLine.isPresent()) {
179 if (detectLineEntry().orElse(null) == ManifestTokenType.CMS_END) {
180 cmsSignatureBuilder.append(currentLine.get());
183 cmsSignatureBuilder.append(currentLine.get()).append("\n");
184 currentLine = readNextNonEmptyLine();
187 if (currentLine.isPresent()) {
188 cmsSignature = cmsSignatureBuilder.toString();
189 readNextNonEmptyLine();
192 if (getCurrentLine().isPresent()) {
193 reportError(Messages.MANIFEST_SIGNATURE_LAST_ENTRY);
194 continueToProcess = false;
199 * Detects the current line manifest token.
201 * @return the current line manifest token.
203 private Optional<ManifestTokenType> detectLineEntry() {
204 final Optional<String> currentLine = getCurrentLine();
205 if (currentLine.isPresent()) {
206 final String line = currentLine.get();
207 final String entry = readEntryName(line).orElse(null);
209 return ManifestTokenType.parse(line);
211 return ManifestTokenType.parse(entry);
214 return Optional.empty();
218 * Validates the manifest metadata content, reporting errors found.
220 * @return {@code true} if the metadata content is valid, {@code false} otherwise.
222 private boolean validateMetadata() {
223 if (metadata.isEmpty()) {
224 reportError(Messages.MANIFEST_NO_METADATA);
228 final Entry<String, String> firstManifestEntry = metadata.entrySet().iterator().next();
229 final ManifestTokenType firstManifestEntryTokenType =
230 ManifestTokenType.parse(firstManifestEntry.getKey()).orElse(null);
231 if (firstManifestEntryTokenType == null) {
232 reportError(Messages.MANIFEST_METADATA_INVALID_ENTRY1, firstManifestEntry.getKey());
235 for (final Entry<String, String> manifestEntry : metadata.entrySet()) {
236 final ManifestTokenType manifestEntryTokenType = ManifestTokenType.parse(manifestEntry.getKey())
238 if (manifestEntryTokenType == null) {
239 reportError(Messages.MANIFEST_METADATA_INVALID_ENTRY1, manifestEntry.getKey());
242 if ((firstManifestEntryTokenType.isMetadataVnfEntry() && !manifestEntryTokenType.isMetadataVnfEntry())
243 || (firstManifestEntryTokenType.isMetadataPnfEntry() && !manifestEntryTokenType.isMetadataPnfEntry())) {
244 reportError(Messages.MANIFEST_METADATA_UNEXPECTED_ENTRY_TYPE);
249 if (metadata.entrySet().size() != MAX_ALLOWED_MANIFEST_META_ENTRIES) {
250 reportError(Messages.MANIFEST_METADATA_DOES_NOT_MATCH_LIMIT, MAX_ALLOWED_MANIFEST_META_ENTRIES);
258 * Processes a Manifest {@link ManifestTokenType#SOURCE} entry.
260 private void processSource() {
261 final Optional<String> currentLine = getCurrentLine();
262 if (!currentLine.isPresent()) {
265 final ManifestTokenType manifestTokenType = detectLineEntry().orElse(null);
266 if (manifestTokenType != ManifestTokenType.SOURCE) {
270 final String sourceLine = currentLine.get();
271 final String sourcePath = readEntryValue(sourceLine).orElse(null);
273 if (sourcePath == null) {
274 reportError(Messages.MANIFEST_EXPECTED_SOURCE_PATH);
277 sources.add(sourcePath);
278 readAlgorithmEntry(sourcePath);
282 * Processes entries {@link ManifestTokenType#ALGORITHM} and {@link ManifestTokenType#HASH} of a {@link
283 * ManifestTokenType#SOURCE} entry.
285 * @param sourcePath the source path related to the algorithm entry.
287 private void readAlgorithmEntry(final String sourcePath) {
288 Optional<String> currentLine = readNextNonEmptyLine();
289 if (!currentLine.isPresent()) {
292 final ManifestTokenType manifestTokenType = detectLineEntry().orElse(null);
293 if (manifestTokenType == ManifestTokenType.HASH) {
294 reportError(Messages.MANIFEST_EXPECTED_ALGORITHM_BEFORE_HASH);
295 continueToProcess = false;
298 if (manifestTokenType != ManifestTokenType.ALGORITHM) {
301 final String algorithmLine = currentLine.get();
302 final String algorithmType = readEntryValue(algorithmLine).orElse(null);
303 if (algorithmType == null) {
304 reportError(Messages.MANIFEST_EXPECTED_ALGORITHM_VALUE);
305 continueToProcess = false;
309 currentLine = readNextNonEmptyLine();
310 if (!currentLine.isPresent() || detectLineEntry().orElse(null) != ManifestTokenType.HASH) {
311 reportError(Messages.MANIFEST_EXPECTED_HASH_ENTRY);
312 continueToProcess = false;
316 final String hashLine = currentLine.get();
317 final String hash = readEntryValue(hashLine).orElse(null);
319 reportError(Messages.MANIFEST_EXPECTED_HASH_VALUE);
320 continueToProcess = false;
323 sourceAndChecksumMap.put(sourcePath, new AlgorithmDigest(algorithmType, hash));
324 readNextNonEmptyLine();