summaryrefslogtreecommitdiffstats
path: root/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/restconfapicall/RestconfApiUtils.java
blob: 134868c151b5996a1c134092984ce01fdac41705 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
/*-
 * ============LICENSE_START=======================================================
 * ONAP - CCSDK
 * ================================================================================
 * Copyright (C) 2018 Huawei Technologies Co., Ltd. All rights reserved.
 *
 * Modifications Copyright © 2018 IBM.
 * Modifications Copyright (c) 2021 AT&T
 * ================================================================================
 * 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.
 * ============LICENSE_END=========================================================
 */

package org.onap.ccsdk.sli.plugins.restconfapicall;

import static org.onap.ccsdk.sli.plugins.restapicall.RestapiCallNode.getParameters;
import static org.onap.ccsdk.sli.plugins.restapicall.RestapiCallNode.parseParam;
import static org.opendaylight.yangtools.yang.model.repo.api.YangTextSchemaSource.forFile;
import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import org.onap.ccsdk.sli.core.sli.SvcLogicException;
import org.onap.ccsdk.sli.plugins.restapicall.HttpMethod;
import org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.YangParameters;
import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
import org.opendaylight.yangtools.yang.model.parser.api.YangParser;
import org.opendaylight.yangtools.yang.model.parser.api.YangParserException;
import org.opendaylight.yangtools.yang.model.parser.api.YangParserFactory;
import org.opendaylight.yangtools.yang.model.parser.api.YangSyntaxErrorException;

/**
 * Utilities for restconf api call node.
 */
public final class RestconfApiUtils {

    static final String RES_CODE = "response-code";

    static final String HTTP_REQ ="httpRequest";

    static final String RES_PRE = "responsePrefix";

    static final String RES_MSG = "response-message";

    static final String HEADER = "header.";

    static final String COMMA = ",";

    static final String COLON = ":";

    static final String HTTP_RES = "httpResponse";

    static final String REST_API_URL = "restapiUrl";

    static final String UPDATED_URL = "URL was set to";

    static final String COMM_FAIL = "Failed to communicate with host %s." +
            "Request will be re-attempted using the host %s.";

    static final String RETRY_COUNT = "This is retry attempt %d out of %d";

    static final String RETRY_FAIL = "Retry attempt has failed. No further " +
            "retry shall be attempted, calling setFailureResponseStatus";

    static final String NO_MORE_RETRY = "Could not attempt retry";

    static final String MAX_RETRY_ERR = "Maximum retries reached, calling " +
            "setFailureResponseStatus";

    static final String ATTEMPTS_MSG = "%d attempts were made out of %d " +
            "maximum retries";

    static final String REQ_ERR = "Error sending the request: ";

    private static final String SLASH = "/";

    private static final String DIR_PATH = "dirPath";

    private static final String URL_SYNTAX = "The following URL cannot be " +
            "parsed into URI : ";

    private static final String YANG = ".yang";

    private static final String YANG_FILE_ERR = "Unable to parse the YANG " +
            "file provided";

    //No instantiation.
    private RestconfApiUtils() {
    }

    /**
     * Returns the YANG parameters after parsing it from the map.
     *
     * @param paramMap parameters map
     * @return YANG parameters
     * @throws SvcLogicException when parsing of parameters map fail
     */
    static YangParameters getYangParameters(Map<String, String> paramMap)
            throws SvcLogicException {
        YangParameters param = (YangParameters) getParameters(
                paramMap, new YangParameters());
        param.dirPath = parseParam(paramMap, DIR_PATH, false, null);
        return param;
    }

    /**
     * Parses the restconf URL and gives the YANG path from it, which can be
     * used to get schema node. If it is a PUT operation, then a node must be
     * reduced from the url to make it always point to the parent.
     *
     * @param url    restconf URL
     * @param method HTTP operation
     * @return YANG path pointing to parent
     * @throws SvcLogicException when parsing the URL fails
     */
    public static String parseUrl(String url, HttpMethod method)
            throws SvcLogicException {
        URI uri;
        try {
            uri = new URI(url);
        } catch (URISyntaxException e) {
            throw new SvcLogicException(URL_SYNTAX + url, e);
        }

        String path = uri.getPath();
        path = getParsedPath(path);
        return path;
    }

    /**
     * Returns the path which contains only the schema nodes.
     *
     * @param path path
     * @return path representing schema
     */
    private static String getParsedPath(String path) {
        String firstHalf;
        String secondHalf;
        if (path.contains(COLON)) {
            String[] p = path.split(COLON);
            if (p[0].contains(SLASH)) {
                int slash = p[0].lastIndexOf(SLASH);
                firstHalf = p[0].substring(slash + 1);
            } else {
                firstHalf = p[0];
            }
            secondHalf = path.substring(p[0].length() + 1);
            return firstHalf + COLON + secondHalf;
        } else if (path.contains(SLASH)) {
            String[] p = path.split(SLASH);
            if (p.length > 4) {
                String actual = p[3] + COLON + p[4];
                if (p.length > 5) {
                    secondHalf = path.substring(
                           p[1].length() + p[2].length() + actual.length() + 3);
                    path = actual + secondHalf;
                } else {
                    path = actual;
                }
            }
        }
        return path;
    }

    /**
     * Returns the schema context of the YANG files present in a directory.
     *
     * @param di directory path
     * @return YANG schema context
     * @throws SvcLogicException when YANG file reading fails
     */
    static EffectiveModelContext getSchemaCtxFromDir(YangParserFactory parserFactory, String di)
            throws SvcLogicException {
        Path d = Paths.get(di);
        File dir = d.toFile();
        List<File> yangFiles = new LinkedList<>();
        getYangFiles(dir, yangFiles);
        YangParser parser = parserFactory.createParser();
        for (File file : yangFiles) {
            try {
                parser.addSource(forFile(file));
            } catch (IOException | YangSyntaxErrorException e) {
                throw new SvcLogicException(YANG_FILE_ERR + e.getMessage(), e);
            }
        }

        try {
            return parser.buildEffectiveModel();
        } catch (YangParserException e) {
            throw new SvcLogicException(YANG_FILE_ERR + e.getMessage(), e);
        }
    }

    /**
     * Returns all the YANG files present in a directory recursively.
     *
     * @param dir       path of the directory
     * @param yangFiles list of YANG files
     */
    private static void getYangFiles(File dir, List<File> yangFiles) {
        if (dir.exists()) {
            File[] files = dir.listFiles();
            if (files != null) {
                processFiles(files, yangFiles);
            }
        }
    }

    /**
     * Processes all the obtained files by isolating all the YANG files from
     * all the directory of the given path recursively.
     *
     * @param files     files in the given path
     * @param yangFiles YANG files list
     */
    private static void processFiles(File[] files, List<File> yangFiles) {
        for (File file : files) {
            if (file.isFile() && file.getName().endsWith(YANG)) {
                yangFiles.add(file);
            } else if (file.isDirectory()) {
                getYangFiles(file, yangFiles);
            }
        }
    }

    /**
     * Returns the updated XML request message by adding root node to it.
     *
     * @param req      XML request
     * @param nodeName root node name
     * @param modNs    module namespace of the root node
     * @return updated XML request message
     */
    static String getUpdatedXmlReq(String req, String nodeName, String modNs) {
        String rootNode = "\n<" + nodeName + " xmlns=\"" + modNs +
                "\">\n";
        req = req.replaceFirst("\n", rootNode);
        req = req + "</" + nodeName + ">";
        return req.replaceAll(">\\s+<", "><");
    }
}