2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
6 * Copyright © 2017 Amdocs
7 * ================================================================================
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 * ============LICENSE_END=========================================================
21 * ECOMP is a trademark and service mark of AT&T Intellectual Property.
23 package org.onap.aai.datarouter.query;
25 import java.security.InvalidParameterException;
26 import java.util.regex.Matcher;
27 import java.util.regex.Pattern;
29 import javax.ws.rs.BadRequestException;
31 import org.apache.camel.Exchange;
32 import org.apache.camel.RuntimeCamelException;
33 import org.onap.aai.rest.RestClientEndpoint;
34 import org.onap.aai.cl.api.Logger;
35 import org.onap.aai.cl.eelf.LoggerFactory;
37 public class ChameleonRouter extends QueryRouter {
39 Logger logger = LoggerFactory.getInstance().getLogger(ChameleonRouter.class.getName());
41 private String chameleonBaseURL;
43 private enum ChameleonAction {
44 GET_OBJECT_BY_ID, GET_REL_BY_ID, GET_OBJECT_RELS, GET_OBJECTS_BY_FILTER, GET_RELS_BY_FILTER
47 private static final Pattern QUERY_OBJECT_FILTER_URL_MATCH = Pattern.compile("/objects/filter(.*)");
48 private static final Pattern QUERY_REL_FILTER_URL_MATCH = Pattern.compile("/relationships/filter(.*)");
49 private static final Pattern QUERY_OBJECT_REL_URL_MATCH = Pattern.compile("/objects/relationships/(.*)");
50 private static final Pattern QUERY_OBJECT_ID_URL_MATCH = Pattern.compile("/objects/(.*)");
51 private static final Pattern QUERY_REL_ID_URL_MATCH = Pattern.compile("/relationships/(.*)");
53 private static final String ECOMP_QUERY_ID = "ECOMP_QUERY_ID";
54 private static final String ECOMP_QUERY_TYPE = "ECOMP_QUERY_TYPE";
56 public ChameleonRouter(String chameleonBaseURL) {
57 String baseURL = chameleonBaseURL.endsWith("/") ? chameleonBaseURL.substring(0, chameleonBaseURL.length() - 1)
59 if (checkRecursion(baseURL)) {
60 logger.error(QueryMsgs.QUERY_ERROR,
61 "Invalid chameleonBaseURL : Can't re-route back to DataRouter " + chameleonBaseURL);
62 throw new InvalidParameterException(
63 "Invalid chameleonBaseURL : Can't re-route back to DataRouter " + chameleonBaseURL);
65 this.chameleonBaseURL = baseURL;
68 public void setQueryRequest(Exchange exchange) {
70 ChameleonAction action = resolveChameleonAction(exchange);
71 String ecompUrl = buildUrl(exchange, action);
72 logger.info(QueryMsgs.QUERY_INFO, "Routing request to Chameleon service URL: " + ecompUrl);
73 exchange.getIn().setHeader(RestClientEndpoint.IN_HEADER_URL, ecompUrl);
74 exchange.getIn().setHeader("X-FromAppId", SERVICE_NAME);
75 exchange.getIn().setHeader("X-TransactionId", getTxId(exchange));
79 private boolean urlMatcher(Pattern p, String url) {
80 Matcher m = p.matcher(url);
81 if (m.matches() && !m.group(1).contains("/")) {
88 private ChameleonAction resolveChameleonAction(Exchange exchange) {
89 String path = exchange.getIn().getHeader(Exchange.HTTP_PATH, String.class);
90 path = path.endsWith("/") ? path.substring(0, path.length() - 1) : path;
91 ChameleonAction action;
93 if (urlMatcher(QUERY_OBJECT_FILTER_URL_MATCH, path)) {
94 action = ChameleonAction.GET_OBJECTS_BY_FILTER;
95 } else if (urlMatcher(QUERY_REL_FILTER_URL_MATCH, path)) {
96 action = ChameleonAction.GET_RELS_BY_FILTER;
97 } else if (urlMatcher(QUERY_OBJECT_REL_URL_MATCH, path)) {
98 action = ChameleonAction.GET_OBJECT_RELS;
99 } else if (urlMatcher(QUERY_OBJECT_ID_URL_MATCH, path)) {
100 action = ChameleonAction.GET_OBJECT_BY_ID;
101 } else if (urlMatcher(QUERY_REL_ID_URL_MATCH, path)) {
102 action = ChameleonAction.GET_REL_BY_ID;
104 exchange.getIn().setHeader(ChameleonErrorProcessor.ECOMP_QUERY_ERROR_CODE, 404);
105 throw new RuntimeCamelException();
110 private String buildUrl(Exchange exchange, ChameleonAction action) {
111 String path = exchange.getIn().getHeader(Exchange.HTTP_PATH, String.class);
112 path = path.endsWith("/") ? path.substring(0, path.length() - 1) : path;
113 String queryParams = exchange.getIn().getHeader(Exchange.HTTP_QUERY, String.class);
114 String ecompUrl = "";
118 case GET_OBJECT_BY_ID:
119 ID = path.substring(path.lastIndexOf("/") + 1, path.length());
120 if (ID == null || ID.isEmpty()) {
121 throw new IllegalArgumentException("Invalid URI path with no Object ID: " + path);
123 if (queryParams != null && !queryParams.isEmpty()) {
124 ecompUrl = chameleonBaseURL + "/" + ID + "?" + queryParams;
127 ecompUrl = chameleonBaseURL + "/" + ID;
130 exchange.getIn().setHeader(ECOMP_QUERY_ID, ID);
131 exchange.getIn().setHeader(ECOMP_QUERY_TYPE, ChameleonAction.GET_OBJECT_BY_ID);
135 ID = path.substring(path.lastIndexOf("/") + 1, path.length());
136 if (ID == null || ID.isEmpty()) {
137 throw new IllegalArgumentException("Invalid URI path with no Relationship ID: " + path);
139 if (queryParams != null && !queryParams.isEmpty()) {
140 ecompUrl = chameleonBaseURL + "/" + ID + "?" + queryParams;
143 ecompUrl = chameleonBaseURL + "/" + ID;
146 exchange.getIn().setHeader(ECOMP_QUERY_ID, ID);
147 exchange.getIn().setHeader(ECOMP_QUERY_TYPE, ChameleonAction.GET_REL_BY_ID);
150 case GET_OBJECT_RELS:
151 ID = path.substring(path.lastIndexOf("/") + 1, path.length());
152 if (ID == null || ID.isEmpty()) {
153 throw new IllegalArgumentException("Invalid URI path with no Object ID: " + path);
155 if (queryParams != null && !queryParams.isEmpty()) {
156 // TODO: Fix the URL for getting object relations when Chameloen
158 ecompUrl = chameleonBaseURL + "/relations" + ID + "?" + queryParams;
161 ecompUrl = chameleonBaseURL + "/relations" + ID;
164 exchange.getIn().setHeader(ECOMP_QUERY_ID, ID);
165 exchange.getIn().setHeader(ECOMP_QUERY_TYPE, ChameleonAction.GET_OBJECT_RELS);
168 case GET_OBJECTS_BY_FILTER:
169 if (queryParams != null && !queryParams.isEmpty()) {
170 // TODO: Fix the URL for getting object filter when Chameloen
172 ecompUrl = chameleonBaseURL + "/filter?" + queryParams;
174 ecompUrl = chameleonBaseURL + "/filter";
176 exchange.getIn().setHeader(ECOMP_QUERY_TYPE, ChameleonAction.GET_OBJECTS_BY_FILTER);
179 case GET_RELS_BY_FILTER:
180 if (queryParams != null && !queryParams.isEmpty()) {
181 // TODO: Fix the URL for getting rel filter when Chameloen
183 ecompUrl = chameleonBaseURL + "/filter?" + queryParams;
185 ecompUrl = chameleonBaseURL + "/filter";
187 exchange.getIn().setHeader(ECOMP_QUERY_TYPE, ChameleonAction.GET_RELS_BY_FILTER);
195 public void setQueryResponse(Exchange exchange) {
196 parseResponse(exchange);
197 adjustHeaders(exchange);
200 private void adjustHeaders(Exchange exchange) {
201 // Remove the internal heders
202 exchange.getIn().removeHeader(ECOMP_QUERY_ID);
203 exchange.getIn().removeHeader(ECOMP_QUERY_TYPE);
206 private void parseResponse(Exchange exchange) throws BadRequestException {
208 ChameleonAction action = exchange.getIn().getHeader(ECOMP_QUERY_TYPE, ChameleonAction.class);
209 Integer httpResponseCode = exchange.getIn().getHeader(RestClientEndpoint.OUT_HEADER_RESPONSE_CODE, Integer.class);
213 case GET_OBJECT_BY_ID:
214 if (httpResponseCode >= 200 && httpResponseCode <= 299) {
215 ID = exchange.getIn().getHeader(ECOMP_QUERY_ID, String.class);
216 if (ID == null || ID.isEmpty()) {
217 exchange.getIn().setHeader(Exchange.HTTP_RESPONSE_CODE, 400);
219 ChameleonResponseBuiler.buildEntity(exchange, ID);
222 exchange.getIn().setHeader(Exchange.HTTP_RESPONSE_CODE, httpResponseCode);
226 if (httpResponseCode >= 200 && httpResponseCode <= 299) {
227 ID = exchange.getIn().getHeader(ECOMP_QUERY_ID, String.class);
228 if (ID == null || ID.isEmpty()) {
229 exchange.getIn().setHeader(Exchange.HTTP_RESPONSE_CODE, 400);
231 ChameleonResponseBuiler.buildEntity(exchange, ID);
234 exchange.getIn().setHeader(Exchange.HTTP_RESPONSE_CODE, httpResponseCode);
237 case GET_OBJECT_RELS:
238 if (httpResponseCode >= 200 && httpResponseCode <= 299) {
239 ID = exchange.getIn().getHeader(ECOMP_QUERY_ID, String.class);
240 if (ID == null || ID.isEmpty()) {
241 exchange.getIn().setHeader(Exchange.HTTP_RESPONSE_CODE, 400);
243 ChameleonResponseBuiler.buildObjectRelationship(exchange, ID);
246 // TODO:Return 200 with empty body for now until chameleon supports this
248 exchange.getIn().setHeader(Exchange.HTTP_RESPONSE_CODE, 200);
249 exchange.getIn().setBody("[]");
252 case GET_OBJECTS_BY_FILTER:
253 if (httpResponseCode >= 200 && httpResponseCode <= 299) {
254 ChameleonResponseBuiler.buildCollection(exchange);
256 // TODO:Return 200 with empty body for now until chameleon supports this
258 exchange.getIn().setHeader(Exchange.HTTP_RESPONSE_CODE, 200);
259 exchange.getIn().setBody("[]");
262 case GET_RELS_BY_FILTER:
263 if (httpResponseCode >= 200 && httpResponseCode <= 299) {
264 ChameleonResponseBuiler.buildCollection(exchange);
266 // TODO:Return 200 with empty body for now until chameleon supports this
268 exchange.getIn().setHeader(Exchange.HTTP_RESPONSE_CODE, 200);
269 exchange.getIn().setBody("[]");