2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2018 Huawei Technologies Co., Ltd. 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.sli.plugins.restconfapicall;
23 import org.onap.ccsdk.sli.core.sli.SvcLogicException;
24 import org.onap.ccsdk.sli.plugins.restapicall.HttpMethod;
25 import org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.YangParameters;
26 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
27 import org.opendaylight.yangtools.yang.model.parser.api.YangSyntaxErrorException;
28 import org.opendaylight.yangtools.yang.parser.rfc7950.repo.YangStatementStreamSource;
29 import org.opendaylight.yangtools.yang.parser.spi.meta.ReactorException;
30 import org.opendaylight.yangtools.yang.parser.stmt.reactor.CrossSourceStatementReactor;
33 import java.io.IOException;
35 import java.net.URISyntaxException;
36 import java.nio.file.Path;
37 import java.nio.file.Paths;
38 import java.util.ArrayList;
39 import java.util.Collection;
40 import java.util.LinkedList;
41 import java.util.List;
44 import static org.onap.ccsdk.sli.plugins.restapicall.HttpMethod.PUT;
45 import static org.onap.ccsdk.sli.plugins.restapicall.RestapiCallNode.getParameters;
46 import static org.onap.ccsdk.sli.plugins.restapicall.RestapiCallNode.parseParam;
47 import static org.opendaylight.yangtools.yang.model.repo.api.StatementParserMode.DEFAULT_MODE;
48 import static org.opendaylight.yangtools.yang.model.repo.api.YangTextSchemaSource.forFile;
49 import static org.opendaylight.yangtools.yang.parser.rfc7950.reactor.RFC7950Reactors.defaultReactor;
50 import static org.opendaylight.yangtools.yang.parser.rfc7950.repo.YangStatementStreamSource.create;
53 * Utilities for restconf api call node.
55 public final class RestconfApiUtils {
57 static final String RES_CODE = "response-code";
59 static final String HTTP_REQ ="httpRequest";
61 static final String RES_PRE = "responsePrefix";
63 static final String RES_MSG = "response-message";
65 static final String HEADER = "header.";
67 static final String COMMA = ",";
69 static final String HTTP_RES = "httpResponse";
71 static final String REST_API_URL = "restapiUrl";
73 static final String UPDATED_URL = "URL was set to";
75 static final String COMM_FAIL = "Failed to communicate with host %s." +
76 "Request will be re-attempted using the host %s.";
78 static final String RETRY_COUNT = "This is retry attempt %d out of %d";
80 static final String RETRY_FAIL = "Retry attempt has failed. No further " +
81 "retry shall be attempted, calling setFailureResponseStatus";
83 static final String NO_MORE_RETRY = "Could not attempt retry";
85 static final String MAX_RETRY_ERR = "Maximum retries reached, calling " +
86 "setFailureResponseStatus";
88 static final String ATTEMPTS_MSG = "%d attempts were made out of %d " +
91 static final String REQ_ERR = "Error sending the request: ";
93 private static final String SLASH = "/";
95 private static final String DIR_PATH = "dirPath";
97 private static final String URL_SYNTAX = "The following URL cannot be " +
100 private static final String PUT_NODE_ERR = "The following URL does not " +
101 "contain minimum two nodes for PUT operation.";
103 private static final String YANG = ".yang";
105 private static final String YANG_FILE_ERR = "Unable to parse the YANG " +
109 private RestconfApiUtils() {
113 * Returns the YANG parameters after parsing it from the map.
115 * @param paramMap parameters map
116 * @return YANG parameters
117 * @throws SvcLogicException when parsing of parameters map fail
119 static YangParameters getYangParameters(Map<String, String> paramMap)
120 throws SvcLogicException {
121 YangParameters param = (YangParameters) getParameters(
122 paramMap, new YangParameters());
123 param.dirPath = parseParam(paramMap, DIR_PATH, false, null);
128 * Parses the restconf URL and gives the YANG path from it, which can be
129 * used to get schema node. If it is a PUT operation, then a node must be
130 * reduced from the url to make it always point to the parent.
132 * @param url restconf URL
133 * @param method HTTP operation
134 * @return YANG path pointing to parent
135 * @throws SvcLogicException when parsing the URL fails
137 public static String parseUrl(String url, HttpMethod method)
138 throws SvcLogicException {
142 } catch (URISyntaxException e) {
143 throw new SvcLogicException(URL_SYNTAX + url, e);
146 String path = uri.getPath();
147 path = getParsedPath(path);
149 if (!path.contains(SLASH)) {
150 throw new SvcLogicException(PUT_NODE_ERR + url);
152 path = path.substring(0, path.lastIndexOf(SLASH));
158 * Returns the path which contains only the schema nodes.
161 * @return path representing schema
163 private static String getParsedPath(String path) {
165 if (path.contains(":")) {
166 String[] p = path.split(":");
167 if (p[0].contains(SLASH)) {
168 int slash = p[0].lastIndexOf(SLASH);
169 firstHalf = p[0].substring(slash + 1);
173 return firstHalf + ":" + p[1];
179 * Returns the schema context of the YANG files present in a directory.
181 * @param di directory path
182 * @return YANG schema context
183 * @throws SvcLogicException when YANG file reading fails
185 static SchemaContext getSchemaCtxFromDir(String di)
186 throws SvcLogicException {
187 Path d = Paths.get(di);
188 File dir = d.toFile();
189 List<File> yangFiles = new LinkedList<>();
190 getYangFiles(dir, yangFiles);
191 final Collection<YangStatementStreamSource> sources =
192 new ArrayList<>(yangFiles.size());
193 for (File file : yangFiles) {
195 sources.add(create(forFile(file)));
196 } catch (IOException | YangSyntaxErrorException e) {
197 throw new SvcLogicException(YANG_FILE_ERR + e.getMessage(), e);
201 final CrossSourceStatementReactor.BuildAction reactor = defaultReactor()
202 .newBuild(DEFAULT_MODE).addSources(sources);
204 return reactor.buildEffective();
205 } catch (ReactorException e) {
206 throw new SvcLogicException(YANG_FILE_ERR + e.getMessage(), e);
211 * Returns all the YANG files present in a directory recursively.
213 * @param dir path of the directory
214 * @param yangFiles list of YANG files
216 private static void getYangFiles(File dir, List<File> yangFiles) {
218 File[] files = dir.listFiles();
220 processFiles(files, yangFiles);
225 private static void processFiles(File[] files, List<File> yangFiles) {
226 for (File file : files) {
227 if (file.isFile() && file.getName().endsWith(YANG)) {
229 } else if (file.isDirectory()) {
230 getYangFiles(file, yangFiles);