2 * ============LICENSE_START====================================================
4 * ===========================================================================
5 * Copyright (c) 2018 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.
18 * ============LICENSE_END====================================================
22 package org.onap.aaf.auth.locate.facade;
25 import static org.onap.aaf.auth.layer.Result.ERR_ActionNotCompleted;
26 import static org.onap.aaf.auth.layer.Result.ERR_BadData;
27 import static org.onap.aaf.auth.layer.Result.ERR_ConflictAlreadyExists;
28 import static org.onap.aaf.auth.layer.Result.ERR_Denied;
29 import static org.onap.aaf.auth.layer.Result.ERR_NotFound;
30 import static org.onap.aaf.auth.layer.Result.ERR_NotImplemented;
31 import static org.onap.aaf.auth.layer.Result.ERR_Policy;
32 import static org.onap.aaf.auth.layer.Result.ERR_Security;
33 import static org.onap.aaf.auth.layer.Result.OK;
35 import java.lang.reflect.Method;
36 import java.util.HashMap;
39 import javax.servlet.http.HttpServletRequest;
40 import javax.servlet.http.HttpServletResponse;
42 import org.onap.aaf.auth.dao.cass.Status;
43 import org.onap.aaf.auth.env.AuthzEnv;
44 import org.onap.aaf.auth.env.AuthzTrans;
45 import org.onap.aaf.auth.layer.FacadeImpl;
46 import org.onap.aaf.auth.layer.Result;
47 import org.onap.aaf.auth.locate.mapper.Mapper;
48 import org.onap.aaf.auth.locate.mapper.Mapper.API;
49 import org.onap.aaf.auth.locate.service.LocateService;
50 import org.onap.aaf.auth.locate.service.LocateServiceImpl;
51 import org.onap.aaf.auth.rserv.RServlet;
52 import org.onap.aaf.auth.rserv.RouteReport;
53 import org.onap.aaf.auth.rserv.doc.ApiDoc;
54 import org.onap.aaf.cadi.aaf.client.Examples;
55 import org.onap.aaf.misc.env.APIException;
56 import org.onap.aaf.misc.env.Data;
57 import org.onap.aaf.misc.env.Data.TYPE;
58 import org.onap.aaf.misc.env.Env;
59 import org.onap.aaf.misc.env.TimeTaken;
60 import org.onap.aaf.misc.rosetta.env.RosettaDF;
61 import org.onap.aaf.misc.rosetta.env.RosettaData;
63 import locate_local.v1_0.Api;
68 * This Service Facade encapsulates the essence of the API Service can do, and provides
69 * a single created object for elements such as RosettaDF.
71 * The Responsibilities of this class are to:
72 * 1) Interact with the Service Implementation (which might be supported by various kinds of Backend Storage)
73 * 2) Validate incoming data (if applicable)
74 * 3) Convert the Service response into the right Format, and mark the Content Type
75 * a) In the future, we may support multiple Response Formats, aka JSON or XML, based on User Request.
76 * 4) Log Service info, warnings and exceptions as necessary
77 * 5) When asked by the API layer, this will create and write Error content to the OutputStream
79 * Note: This Class does NOT set the HTTP Status Code. That is up to the API layer, so that it can be
80 * clearly coordinated with the API Documentation
85 public abstract class LocateFacadeImpl<IN,OUT,ENDPOINTS,MGMT_ENDPOINTS,CONFIGURATION,ERROR> extends FacadeImpl implements LocateFacade
87 private LocateService<IN,OUT,ENDPOINTS,MGMT_ENDPOINTS,CONFIGURATION,ERROR> service;
89 private final RosettaDF<ERROR> errDF;
90 private final RosettaDF<Api> apiDF;
91 private final RosettaDF<ENDPOINTS> epDF;
92 private final RosettaDF<MGMT_ENDPOINTS> mepDF;
93 private final RosettaDF<CONFIGURATION> confDF;
96 private static long cacheClear = 0L, emptyCheck=0L;
97 private final static Map<String,String> epsCache = new HashMap<String, String>(); // protected manually, in getEndpoints
99 public LocateFacadeImpl(AuthzEnv env, LocateService<IN,OUT,ENDPOINTS,MGMT_ENDPOINTS,CONFIGURATION,ERROR> service, Data.TYPE dataType) throws APIException {
100 this.service = service;
101 (errDF = env.newDataFactory(mapper().getClass(API.ERROR))).in(dataType).out(dataType);
102 (apiDF = env.newDataFactory(Api.class)).in(dataType).out(dataType);
103 (epDF = env.newDataFactory(mapper().getClass(API.ENDPOINTS))).in(dataType).out(dataType);
104 (mepDF = env.newDataFactory(mapper().getClass(API.MGMT_ENDPOINTS))).in(dataType).out(dataType);
105 (confDF = env.newDataFactory(mapper().getClass(API.CONFIG))).in(dataType).out(dataType);
108 public Mapper<IN,OUT,ENDPOINTS,MGMT_ENDPOINTS,CONFIGURATION,ERROR> mapper() {
109 return service.mapper();
113 * @see com.att.authz.facade.AuthzFacade#error(org.onap.aaf.auth.env.test.AuthzTrans, javax.servlet.http.HttpServletResponse, int)
115 * Note: Conforms to AT&T TSS RESTful Error Structure
118 public void error(AuthzTrans trans, HttpServletResponse response, Result<?> result) {
119 String msg = result.details==null?"":result.details.trim();
121 if(result.variables==null) {
122 detail = new String[1];
124 int l = result.variables.length;
125 detail=new String[l+1];
126 System.arraycopy(result.variables, 0, detail, 1, l);
128 error(trans, response, result.status,msg,detail);
132 public void error(AuthzTrans trans, HttpServletResponse response, int status, String msg, String ... _detail) {
133 String[] detail = _detail;
134 if(detail.length==0) {
135 detail=new String[1];
137 boolean hidemsg = false;
141 case ERR_ActionNotCompleted:
143 detail[0] = "Accepted, Action not complete";
144 response.setStatus(/*httpstatus=*/202);
152 detail[0] = "Forbidden";
153 response.setStatus(/*httpstatus=*/403);
159 detail[0] = "Not Found";
160 response.setStatus(/*httpstatus=*/404);
166 detail[0] = "Not Acceptable";
167 response.setStatus(/*httpstatus=*/406);
171 case ERR_ConflictAlreadyExists:
173 detail[0] = "Conflict Already Exists";
174 response.setStatus(/*httpstatus=*/409);
178 case ERR_NotImplemented:
180 detail[0] = "Not Implemented";
181 response.setStatus(/*httpstatus=*/501);
186 detail[0] = "General Service Error";
187 response.setStatus(/*httpstatus=*/500);
193 StringBuilder holder = new StringBuilder();
194 ERROR em = mapper().errorFromMessage(holder,msgId,msg,detail);
203 em = mapper().errorFromMessage(holder, msgId, "Server had an issue processing this request");
205 errDF.newData(trans).load(em).to(response.getOutputStream());
207 } catch (Exception e) {
208 trans.error().log(e,"unable to send response for",msg);
213 * @see com.att.authz.facade.AuthzFacade#getAPI(org.onap.aaf.auth.env.test.AuthzTrans, javax.servlet.http.HttpServletResponse)
215 public final static String API_REPORT = "apiReport";
217 public Result<Void> getAPI(AuthzTrans trans, HttpServletResponse resp, RServlet<AuthzTrans> rservlet) {
218 TimeTaken tt = trans.start(API_REPORT, Env.SUB);
222 Method[] meths = LocateServiceImpl.class.getDeclaredMethods();
223 for(RouteReport rr : rservlet.routeReport()) {
224 api.getRoute().add(ar = new Api.Route());
225 ar.setMeth(rr.meth.name());
228 ar.getContentType().addAll(rr.contextTypes);
229 for(Method m : meths) {
231 if((ad = m.getAnnotation(ApiDoc.class))!=null &&
232 rr.meth.equals(ad.method()) &&
233 rr.path.equals(ad.path())) {
234 for(String param : ad.params()) {
235 ar.getParam().add(param);
237 for(String text : ad.text()) {
238 ar.getComments().add(text);
240 ar.setExpected(ad.expectedCode());
241 for(int ec : ad.errorCodes()) {
242 ar.getExplicitErr().add(ec);
247 apiDF.newData(trans).load(api).to(resp.getOutputStream());
248 setContentType(resp,apiDF.getOutType());
251 } catch (Exception e) {
252 trans.error().log(e,IN,API_REPORT);
253 return Result.err(e);
259 public final static String API_EXAMPLE = "apiExample";
261 * @see com.att.authz.facade.AuthzFacade#getAPIExample(org.onap.aaf.auth.env.test.AuthzTrans, javax.servlet.http.HttpServletResponse, java.lang.String)
264 public Result<Void> getAPIExample(AuthzTrans trans, HttpServletResponse resp, String nameOrContentType, boolean optional) {
265 TimeTaken tt = trans.start(API_EXAMPLE, Env.SUB);
267 String content =Examples.print(apiDF.getEnv(), nameOrContentType, optional);
268 resp.getOutputStream().print(content);
269 setContentType(resp,content.contains("<?xml")?TYPE.XML:TYPE.JSON);
271 } catch (Exception e) {
272 trans.error().log(e,IN,API_EXAMPLE);
273 return Result.err(Result.ERR_NotImplemented,e.getMessage());
279 public final static String GET_ENDPOINTS = "getEndpoints";
280 private final static Object LOCK = new Object();
282 * @see org.onap.aaf.auth.locate.facade.GwFacade#getEndpoints(org.onap.aaf.auth.env.test.AuthzTrans, javax.servlet.http.HttpServletResponse, java.lang.String, java.lang.String, java.lang.String)
285 public Result<Void> getEndpoints(AuthzTrans trans, HttpServletResponse resp, String key, String service, String version, String other) {
286 TimeTaken tt = trans.start(GET_ENDPOINTS, Env.SUB);
289 long temp=System.currentTimeMillis();
291 if(cacheClear<temp) {
293 cacheClear = temp+1000*60*2; // 2 mins standard cache clear
295 output = epsCache.get(key);
296 if("{}".equals(output) && emptyCheck<temp) {
298 emptyCheck = temp+5000; // 5 second check
303 Result<ENDPOINTS> reps = this.service.getEndPoints(trans,service,version,other);
305 return Result.err(reps);
307 output = epDF.newData(trans).load(reps.value).asString();
309 epsCache.put(key, output);
313 resp.getOutputStream().println(output);
314 setContentType(resp,epDF.getOutType());
316 } catch (Exception e) {
317 trans.error().log(e,IN,API_EXAMPLE);
318 return Result.err(Result.ERR_NotImplemented,e.getMessage());
324 private static final String PUT_MGMT_ENDPOINTS = "Put Mgmt Endpoints";
326 * @see org.onap.aaf.auth.locate.facade.GwFacade#putMgmtEndpoints(org.onap.aaf.auth.env.test.AuthzTrans, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
329 public Result<Void> putMgmtEndpoints(AuthzTrans trans, HttpServletRequest req, HttpServletResponse resp) {
330 TimeTaken tt = trans.start(PUT_MGMT_ENDPOINTS, Env.SUB|Env.ALWAYS);
334 RosettaData<MGMT_ENDPOINTS> data = mepDF.newData().load(req.getInputStream());
335 rreq = data.asObject();
336 } catch(APIException e) {
337 trans.error().log("Invalid Input",IN,PUT_MGMT_ENDPOINTS);
338 return Result.err(Status.ERR_BadData,"Invalid Input");
341 Result<Void> rp = service.putMgmtEndPoints(trans, rreq);
347 setContentType(resp,mepDF.getOutType());
352 } catch (Exception e) {
353 trans.error().log(e,IN,PUT_MGMT_ENDPOINTS);
354 return Result.err(e);
360 private static final String DELETE_MGMT_ENDPOINTS = "Delete Mgmt Endpoints";
362 * @see org.onap.aaf.auth.locate.facade.GwFacade#removeMgmtEndpoints(org.onap.aaf.auth.env.test.AuthzTrans, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
365 public Result<Void> removeMgmtEndpoints(AuthzTrans trans, HttpServletRequest req, HttpServletResponse resp) {
366 TimeTaken tt = trans.start(DELETE_MGMT_ENDPOINTS, Env.SUB|Env.ALWAYS);
370 RosettaData<MGMT_ENDPOINTS> data = mepDF.newData().load(req.getInputStream());
371 rreq = data.asObject();
372 } catch(APIException e) {
373 trans.error().log("Invalid Input",IN,DELETE_MGMT_ENDPOINTS);
374 return Result.err(Status.ERR_BadData,"Invalid Input");
377 Result<Void> rp = service.removeMgmtEndPoints(trans, rreq);
383 setContentType(resp,mepDF.getOutType());
388 } catch (Exception e) {
389 trans.error().log(e,IN,DELETE_MGMT_ENDPOINTS);
390 return Result.err(e);
396 private static final String GET_CONFIG = "Get Configuration";
398 public Result<Void> getConfig(AuthzTrans trans, HttpServletRequest req, HttpServletResponse resp, final String id, final String type) {
399 TimeTaken tt = trans.start(GET_CONFIG, Env.SUB|Env.ALWAYS);
401 Result<CONFIGURATION> rp = service.getConfig(trans, id, type);
404 setContentType(resp,mepDF.getOutType());
405 confDF.newData(trans).load(rp.value).to(resp.getOutputStream());
408 return Result.err(rp);
410 } catch (Exception e) {
411 trans.error().log(e,IN,GET_CONFIG);
412 return Result.err(e);