2 * ============LICENSE_START=======================================================
3 * Copyright (C) 2016-2018 Ericsson. All rights reserved.
4 * Modifications Copyright (C) 2019-2021 Nordix Foundation.
5 * Modifications Copyright (C) 2021 AT&T Intellectual Property. 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.
19 * SPDX-License-Identifier: Apache-2.0
20 * ============LICENSE_END=========================================================
23 package org.onap.policy.apex.service.parameters.carriertechnology;
25 import java.util.Arrays;
26 import java.util.HashSet;
27 import java.util.List;
29 import java.util.regex.Matcher;
30 import java.util.regex.Pattern;
31 import java.util.regex.PatternSyntaxException;
32 import javax.ws.rs.core.MultivaluedHashMap;
33 import javax.ws.rs.core.MultivaluedMap;
35 import lombok.NoArgsConstructor;
37 import org.apache.commons.lang3.StringUtils;
38 import org.onap.policy.common.parameters.BeanValidationResult;
39 import org.onap.policy.common.parameters.ObjectValidationResult;
40 import org.onap.policy.common.parameters.ValidationResult;
41 import org.onap.policy.common.parameters.ValidationStatus;
42 import org.onap.policy.common.utils.validation.ParameterValidationUtils;
43 import org.onap.policy.models.base.Validated;
44 import org.slf4j.Logger;
45 import org.slf4j.LoggerFactory;
49 * Apex plugin parameters for REST as an event carrier technology with Apex.
51 * <p>The parameters for this plugin are:
53 * <li>url: The URL that the Apex Rest client will connect to over REST for event reception or event sending. This
54 * parameter is mandatory.
55 * <li>httpMethod: The HTTP method to use when sending events over REST, legal values are POST (default) and PUT. When
56 * receiving events, the REST client plugin always uses the HTTP GET method.
57 * <li>httpHeaders, the HTTP headers to send on REST requests, optional parameter, defaults to none.
58 * <li>httpCodeFilter: a regular expression filter for returned HTTP codes, if the returned HTTP code passes this
59 * filter, then the request is assumed to have succeeded by the plugin, optional, defaults to allowing 2xx codes
60 * through, that is a regular expression of "[2][0-9][0-9]"
63 * @author Ning Xi(ning.xi@ericsson.com)
69 public class RestPluginCarrierTechnologyParameters extends CarrierTechnologyParameters {
70 // Get a reference to the logger
71 private static final Logger LOGGER = LoggerFactory.getLogger(RestPluginCarrierTechnologyParameters.class);
73 /** The supported HTTP methods. */
75 public enum HttpMethod {
83 /** The default HTTP code filter, allows 2xx HTTP codes through. */
84 public static final String DEFAULT_HTTP_CODE_FILTER = "[2][0-9][0-9]";
86 // Commonly occurring strings
87 private static final String HTTP_HEADERS = "httpHeaders";
88 private static final String HTTP_CODE_FILTER = "httpCodeFilter";
90 // Regular expression patterns for finding and checking keys in URLs
91 private static final Pattern patternProperKey = Pattern.compile("(?<=\\{)[^}]*(?=\\})");
92 protected static final Pattern patternErrorKey = Pattern
93 .compile("(\\{[^\\{}]*.?\\{)|(\\{[^\\{}]*$)|(\\}[^\\{}]*.?\\})|(^[^\\{}]*.?\\})|\\{\\s*\\}");
96 protected String url = null;
97 protected HttpMethod httpMethod = null;
98 protected String[][] httpHeaders = null;
99 protected String httpCodeFilter = DEFAULT_HTTP_CODE_FILTER;
102 * Check if http headers have been set for the REST request.
104 * @return true if headers have been set
106 public boolean checkHttpHeadersSet() {
107 return httpHeaders != null && httpHeaders.length > 0;
111 * Gets the http headers for the REST request as a multivalued map.
113 * @return the headers
115 public MultivaluedMap<String, Object> getHttpHeadersAsMultivaluedMap() {
116 if (httpHeaders == null) {
120 // Load the HTTP headers into the map
121 MultivaluedMap<String, Object> httpHeaderMap = new MultivaluedHashMap<>();
123 for (String[] httpHeader : httpHeaders) {
124 httpHeaderMap.putSingle(httpHeader[0], httpHeader[1]);
127 return httpHeaderMap;
131 * Sets the header for the REST request.
133 * @param httpHeaders the incoming HTTP headers
135 public void setHttpHeaders(final String[][] httpHeaders) {
136 this.httpHeaders = httpHeaders;
140 * Get the tag for the REST Producer Properties.
142 * @return set of the tags
144 public Set<String> getKeysFromUrl() {
145 Matcher matcher = patternProperKey.matcher(getUrl());
146 Set<String> key = new HashSet<>();
147 while (matcher.find()) {
148 key.add(matcher.group());
157 public BeanValidationResult validate() {
158 BeanValidationResult result = super.validate();
160 result.addResult(validateUrl());
161 result.addResult(validateHttpHeaders());
162 result.addResult(validateHttpCodeFilter());
172 * <br/>http://www.blah.com/{par1/somethingelse (Missing end tag) use {[^\\{}]*$
173 * <br/>http://www.blah.com/{par1/{some}thingelse (Nested tag) use {[^}]*{
174 * <br/>http://www.blah.com/{par1}/some}thingelse (Missing start tag1) use }[^{}]*.}
175 * <br/>http://www.blah.com/par1}/somethingelse (Missing start tag2) use }[^{}]*}
176 * <br/>http://www.blah.com/{}/somethingelse (Empty tag) use {[\s]*}
179 public ValidationResult validateUrl() {
180 // The URL may be optional so existence must be checked in the plugin code
181 String url2 = getUrl();
186 var matcher = patternErrorKey.matcher(url2);
187 if (matcher.find()) {
188 final String urlInvalidMessage = "invalid URL has been set for event sending on " + getLabel();
189 return new ObjectValidationResult("url", url2, ValidationStatus.INVALID, urlInvalidMessage);
196 * Validate the HTTP headers.
198 * @return the result of the validation
200 private ValidationResult validateHttpHeaders() {
201 if (httpHeaders == null) {
205 var result = new BeanValidationResult(HTTP_HEADERS, httpHeaders);
208 for (String[] httpHeader : httpHeaders) {
209 final String label = "entry " + (item++);
210 final List<String> value = (httpHeader == null ? null : Arrays.asList(httpHeader));
211 var result2 = new BeanValidationResult(label, value);
213 if (httpHeader == null) {
214 // note: add to result, not result2
215 result.addResult(label, null, ValidationStatus.INVALID, Validated.IS_NULL);
217 } else if (httpHeader.length != 2) {
218 // note: add to result, not result2
219 result.addResult(label, value, ValidationStatus.INVALID, "must have one key and one value");
221 } else if (!ParameterValidationUtils.validateStringParameter(httpHeader[0])) {
222 result2.addResult("key", httpHeader[0], ValidationStatus.INVALID, Validated.IS_BLANK);
224 } else if (!ParameterValidationUtils.validateStringParameter(httpHeader[1])) {
225 result2.addResult("value", httpHeader[1], ValidationStatus.INVALID, Validated.IS_BLANK);
228 result.addResult(result2);
235 * Validate the HTTP code filter.
237 public ValidationResult validateHttpCodeFilter() {
238 if (httpCodeFilter == null) {
239 httpCodeFilter = DEFAULT_HTTP_CODE_FILTER;
241 } else if (StringUtils.isBlank(httpCodeFilter)) {
242 return new ObjectValidationResult(HTTP_CODE_FILTER, httpCodeFilter, ValidationStatus.INVALID,
243 "must be a three digit regular expression");
246 Pattern.compile(httpCodeFilter);
247 } catch (PatternSyntaxException pse) {
248 LOGGER.debug("Invalid HTTP code filter", pse);
249 String message = "Invalid HTTP code filter, the filter must be specified as a three digit "
250 + "regular expression: " + pse.getMessage();
251 return new ObjectValidationResult(HTTP_CODE_FILTER, httpCodeFilter, ValidationStatus.INVALID,
263 public String toString() {
264 return getLabel() + "CarrierTechnologyParameters [url=" + url + ", httpMethod=" + httpMethod + ", httpHeaders="
265 + Arrays.deepToString(httpHeaders) + ", httpCodeFilter=" + httpCodeFilter + "]";