1 /*******************************************************************************
\r
2 * ============LICENSE_START====================================================
\r
4 * * ===========================================================================
\r
5 * * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
\r
6 * * ===========================================================================
\r
7 * * Licensed under the Apache License, Version 2.0 (the "License");
\r
8 * * you may not use this file except in compliance with the License.
\r
9 * * You may obtain a copy of the License at
\r
11 * * http://www.apache.org/licenses/LICENSE-2.0
\r
13 * * Unless required by applicable law or agreed to in writing, software
\r
14 * * distributed under the License is distributed on an "AS IS" BASIS,
\r
15 * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
\r
16 * * See the License for the specific language governing permissions and
\r
17 * * limitations under the License.
\r
18 * * ============LICENSE_END====================================================
\r
20 * * ECOMP is a trademark and service mark of AT&T Intellectual Property.
\r
22 ******************************************************************************/
\r
23 package org.onap.aaf.authz.gw.facade;
\r
26 import static org.onap.aaf.authz.layer.Result.ERR_ActionNotCompleted;
\r
27 import static org.onap.aaf.authz.layer.Result.ERR_BadData;
\r
28 import static org.onap.aaf.authz.layer.Result.ERR_ConflictAlreadyExists;
\r
29 import static org.onap.aaf.authz.layer.Result.ERR_Denied;
\r
30 import static org.onap.aaf.authz.layer.Result.ERR_NotFound;
\r
31 import static org.onap.aaf.authz.layer.Result.ERR_NotImplemented;
\r
32 import static org.onap.aaf.authz.layer.Result.ERR_Policy;
\r
33 import static org.onap.aaf.authz.layer.Result.ERR_Security;
\r
35 import java.lang.reflect.Method;
\r
37 import javax.servlet.http.HttpServletResponse;
\r
39 import org.onap.aaf.authz.env.AuthzEnv;
\r
40 import org.onap.aaf.authz.env.AuthzTrans;
\r
41 import org.onap.aaf.authz.gw.mapper.Mapper;
\r
42 import org.onap.aaf.authz.gw.mapper.Mapper.API;
\r
43 import org.onap.aaf.authz.gw.service.GwService;
\r
44 import org.onap.aaf.authz.gw.service.GwServiceImpl;
\r
45 import org.onap.aaf.authz.layer.FacadeImpl;
\r
46 import org.onap.aaf.authz.layer.Result;
\r
47 import org.onap.aaf.cssa.rserv.RServlet;
\r
48 import org.onap.aaf.cssa.rserv.RouteReport;
\r
49 import org.onap.aaf.cssa.rserv.doc.ApiDoc;
\r
51 import org.onap.aaf.cadi.aaf.client.Examples;
\r
52 import org.onap.aaf.inno.env.APIException;
\r
53 import org.onap.aaf.inno.env.Data;
\r
54 import org.onap.aaf.inno.env.Data.TYPE;
\r
55 import org.onap.aaf.inno.env.Env;
\r
56 import org.onap.aaf.inno.env.TimeTaken;
\r
57 import org.onap.aaf.rosetta.env.RosettaDF;
\r
64 * This Service Facade encapsulates the essence of the API Service can do, and provides
\r
65 * a single created object for elements such as RosettaDF.
\r
67 * The Responsibilities of this class are to:
\r
68 * 1) Interact with the Service Implementation (which might be supported by various kinds of Backend Storage)
\r
69 * 2) Validate incoming data (if applicable)
\r
70 * 3) Convert the Service response into the right Format, and mark the Content Type
\r
71 * a) In the future, we may support multiple Response Formats, aka JSON or XML, based on User Request.
\r
72 * 4) Log Service info, warnings and exceptions as necessary
\r
73 * 5) When asked by the API layer, this will create and write Error content to the OutputStream
\r
75 * Note: This Class does NOT set the HTTP Status Code. That is up to the API layer, so that it can be
\r
76 * clearly coordinated with the API Documentation
\r
80 public abstract class GwFacadeImpl<IN,OUT,ERROR> extends FacadeImpl implements GwFacade
\r
82 private GwService<IN,OUT,ERROR> service;
\r
84 private final RosettaDF<ERROR> errDF;
\r
85 private final RosettaDF<Api> apiDF;
\r
87 public GwFacadeImpl(AuthzEnv env, GwService<IN,OUT,ERROR> service, Data.TYPE dataType) throws APIException {
\r
88 this.service = service;
\r
89 (errDF = env.newDataFactory(mapper().getClass(API.ERROR))).in(dataType).out(dataType);
\r
90 (apiDF = env.newDataFactory(Api.class)).in(dataType).out(dataType);
\r
93 public Mapper<IN,OUT,ERROR> mapper() {
\r
94 return service.mapper();
\r
98 * @see com.att.authz.facade.AuthzFacade#error(org.onap.aaf.authz.env.AuthzTrans, javax.servlet.http.HttpServletResponse, int)
\r
100 * Note: Conforms to AT&T TSS RESTful Error Structure
\r
103 public void error(AuthzTrans trans, HttpServletResponse response, Result<?> result) {
\r
104 String msg = result.details==null?"":result.details.trim();
\r
106 if(result.variables==null) {
\r
107 detail = new String[1];
\r
109 int l = result.variables.length;
\r
110 detail=new String[l+1];
\r
111 System.arraycopy(result.variables, 0, detail, 1, l);
\r
113 error(trans, response, result.status,msg,detail);
\r
117 public void error(AuthzTrans trans, HttpServletResponse response, int status, String msg, String ... _detail) {
\r
118 String[] detail = _detail;
\r
119 if(detail.length==0) {
\r
120 detail=new String[1];
\r
125 case ERR_ActionNotCompleted:
\r
127 detail[0] = "Accepted, Action not complete";
\r
128 response.setStatus(/*httpstatus=*/202);
\r
136 detail[0] = "Forbidden";
\r
137 response.setStatus(/*httpstatus=*/403);
\r
143 detail[0] = "Not Found";
\r
144 response.setStatus(/*httpstatus=*/404);
\r
150 detail[0] = "Not Acceptable";
\r
151 response.setStatus(/*httpstatus=*/406);
\r
155 case ERR_ConflictAlreadyExists:
\r
157 detail[0] = "Conflict Already Exists";
\r
158 response.setStatus(/*httpstatus=*/409);
\r
162 case ERR_NotImplemented:
\r
164 detail[0] = "Not Implemented";
\r
165 response.setStatus(/*httpstatus=*/501);
\r
171 detail[0] = "General Service Error";
\r
172 response.setStatus(/*httpstatus=*/500);
\r
177 StringBuilder holder = new StringBuilder();
\r
178 errDF.newData(trans).load(
\r
179 mapper().errorFromMessage(holder,msgId,msg,detail)).to(response.getOutputStream());
\r
186 } catch (Exception e) {
\r
187 trans.error().log(e,"unable to send response for",msg);
\r
192 * @see com.att.authz.facade.AuthzFacade#getAPI(org.onap.aaf.authz.env.AuthzTrans, javax.servlet.http.HttpServletResponse)
\r
194 public final static String API_REPORT = "apiReport";
\r
196 public Result<Void> getAPI(AuthzTrans trans, HttpServletResponse resp, RServlet<AuthzTrans> rservlet) {
\r
197 TimeTaken tt = trans.start(API_REPORT, Env.SUB);
\r
199 Api api = new Api();
\r
201 Method[] meths = GwServiceImpl.class.getDeclaredMethods();
\r
202 for(RouteReport rr : rservlet.routeReport()) {
\r
203 api.getRoute().add(ar = new Api.Route());
\r
204 ar.setMeth(rr.meth.name());
\r
205 ar.setPath(rr.path);
\r
206 ar.setDesc(rr.desc);
\r
207 ar.getContentType().addAll(rr.contextTypes);
\r
208 for(Method m : meths) {
\r
210 if((ad = m.getAnnotation(ApiDoc.class))!=null &&
\r
211 rr.meth.equals(ad.method()) &&
\r
212 rr.path.equals(ad.path())) {
\r
213 for(String param : ad.params()) {
\r
214 ar.getParam().add(param);
\r
216 for(String text : ad.text()) {
\r
217 ar.getComments().add(text);
\r
219 ar.setExpected(ad.expectedCode());
\r
220 for(int ec : ad.errorCodes()) {
\r
221 ar.getExplicitErr().add(ec);
\r
226 apiDF.newData(trans).load(api).to(resp.getOutputStream());
\r
227 setContentType(resp,apiDF.getOutType());
\r
228 return Result.ok();
\r
230 } catch (Exception e) {
\r
231 trans.error().log(e,IN,API_REPORT);
\r
232 return Result.err(e);
\r
238 public final static String API_EXAMPLE = "apiExample";
\r
240 * @see com.att.authz.facade.AuthzFacade#getAPIExample(org.onap.aaf.authz.env.AuthzTrans, javax.servlet.http.HttpServletResponse, java.lang.String)
\r
243 public Result<Void> getAPIExample(AuthzTrans trans, HttpServletResponse resp, String nameOrContentType, boolean optional) {
\r
244 TimeTaken tt = trans.start(API_EXAMPLE, Env.SUB);
\r
246 String content =Examples.print(apiDF.getEnv(), nameOrContentType, optional);
\r
247 resp.getOutputStream().print(content);
\r
248 setContentType(resp,content.contains("<?xml")?TYPE.XML:TYPE.JSON);
\r
249 return Result.ok();
\r
250 } catch (Exception e) {
\r
251 trans.error().log(e,IN,API_EXAMPLE);
\r
252 return Result.err(Result.ERR_NotImplemented,e.getMessage());
\r