Update project structure to org.onap.aaf
[aaf/authz.git] / authz-gw / src / main / java / org / onap / aaf / authz / gw / facade / GwFacadeImpl.java
diff --git a/authz-gw/src/main/java/org/onap/aaf/authz/gw/facade/GwFacadeImpl.java b/authz-gw/src/main/java/org/onap/aaf/authz/gw/facade/GwFacadeImpl.java
new file mode 100644 (file)
index 0000000..fa61066
--- /dev/null
@@ -0,0 +1,258 @@
+/*******************************************************************************\r
+ * ============LICENSE_START====================================================\r
+ * * org.onap.aaf\r
+ * * ===========================================================================\r
+ * * Copyright © 2017 AT&T Intellectual Property. All rights reserved.\r
+ * * ===========================================================================\r
+ * * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * * you may not use this file except in compliance with the License.\r
+ * * You may obtain a copy of the License at\r
+ * * \r
+ *  *      http://www.apache.org/licenses/LICENSE-2.0\r
+ * * \r
+ *  * Unless required by applicable law or agreed to in writing, software\r
+ * * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * * See the License for the specific language governing permissions and\r
+ * * limitations under the License.\r
+ * * ============LICENSE_END====================================================\r
+ * *\r
+ * * ECOMP is a trademark and service mark of AT&T Intellectual Property.\r
+ * *\r
+ ******************************************************************************/\r
+package org.onap.aaf.authz.gw.facade;\r
+\r
+\r
+import static org.onap.aaf.authz.layer.Result.ERR_ActionNotCompleted;\r
+import static org.onap.aaf.authz.layer.Result.ERR_BadData;\r
+import static org.onap.aaf.authz.layer.Result.ERR_ConflictAlreadyExists;\r
+import static org.onap.aaf.authz.layer.Result.ERR_Denied;\r
+import static org.onap.aaf.authz.layer.Result.ERR_NotFound;\r
+import static org.onap.aaf.authz.layer.Result.ERR_NotImplemented;\r
+import static org.onap.aaf.authz.layer.Result.ERR_Policy;\r
+import static org.onap.aaf.authz.layer.Result.ERR_Security;\r
+\r
+import java.lang.reflect.Method;\r
+\r
+import javax.servlet.http.HttpServletResponse;\r
+\r
+import org.onap.aaf.authz.env.AuthzEnv;\r
+import org.onap.aaf.authz.env.AuthzTrans;\r
+import org.onap.aaf.authz.gw.mapper.Mapper;\r
+import org.onap.aaf.authz.gw.mapper.Mapper.API;\r
+import org.onap.aaf.authz.gw.service.GwService;\r
+import org.onap.aaf.authz.gw.service.GwServiceImpl;\r
+import org.onap.aaf.authz.layer.FacadeImpl;\r
+import org.onap.aaf.authz.layer.Result;\r
+import org.onap.aaf.cssa.rserv.RServlet;\r
+import org.onap.aaf.cssa.rserv.RouteReport;\r
+import org.onap.aaf.cssa.rserv.doc.ApiDoc;\r
+\r
+import org.onap.aaf.cadi.aaf.client.Examples;\r
+import org.onap.aaf.inno.env.APIException;\r
+import org.onap.aaf.inno.env.Data;\r
+import org.onap.aaf.inno.env.Data.TYPE;\r
+import org.onap.aaf.inno.env.Env;\r
+import org.onap.aaf.inno.env.TimeTaken;\r
+import org.onap.aaf.rosetta.env.RosettaDF;\r
+\r
+import gw.v1_0.Api;\r
+\r
+/**\r
+ * AuthzFacade\r
+ * \r
+ * This Service Facade encapsulates the essence of the API Service can do, and provides\r
+ * a single created object for elements such as RosettaDF.\r
+ *\r
+ * The Responsibilities of this class are to:\r
+ * 1) Interact with the Service Implementation (which might be supported by various kinds of Backend Storage)\r
+ * 2) Validate incoming data (if applicable)\r
+ * 3) Convert the Service response into the right Format, and mark the Content Type\r
+ *             a) In the future, we may support multiple Response Formats, aka JSON or XML, based on User Request.\r
+ * 4) Log Service info, warnings and exceptions as necessary\r
+ * 5) When asked by the API layer, this will create and write Error content to the OutputStream\r
+ * \r
+ * Note: This Class does NOT set the HTTP Status Code.  That is up to the API layer, so that it can be \r
+ * clearly coordinated with the API Documentation\r
+ * \r
+ *\r
+ */\r
+public abstract class GwFacadeImpl<IN,OUT,ERROR> extends FacadeImpl implements GwFacade \r
+       {\r
+       private GwService<IN,OUT,ERROR> service;\r
+\r
+       private final RosettaDF<ERROR>          errDF;\r
+       private final RosettaDF<Api>            apiDF;\r
+\r
+       public GwFacadeImpl(AuthzEnv env, GwService<IN,OUT,ERROR> service, Data.TYPE dataType) throws APIException {\r
+               this.service = service;\r
+               (errDF                          = env.newDataFactory(mapper().getClass(API.ERROR))).in(dataType).out(dataType);\r
+               (apiDF                          = env.newDataFactory(Api.class)).in(dataType).out(dataType);\r
+       }\r
+       \r
+       public Mapper<IN,OUT,ERROR> mapper() {\r
+               return service.mapper();\r
+       }\r
+               \r
+       /* (non-Javadoc)\r
+        * @see com.att.authz.facade.AuthzFacade#error(org.onap.aaf.authz.env.AuthzTrans, javax.servlet.http.HttpServletResponse, int)\r
+        * \r
+        * Note: Conforms to AT&T TSS RESTful Error Structure\r
+        */\r
+       @Override\r
+       public void error(AuthzTrans trans, HttpServletResponse response, Result<?> result) {\r
+               String msg = result.details==null?"":result.details.trim();\r
+               String[] detail;\r
+               if(result.variables==null) {\r
+                       detail = new String[1];\r
+               } else {\r
+                       int l = result.variables.length;\r
+                       detail=new String[l+1];\r
+                       System.arraycopy(result.variables, 0, detail, 1, l);\r
+               }\r
+               error(trans, response, result.status,msg,detail);\r
+       }\r
+               \r
+       @Override\r
+       public void error(AuthzTrans trans, HttpServletResponse response, int status, String msg, String ... _detail) {\r
+               String[] detail = _detail;\r
+               if(detail.length==0) {\r
+                   detail=new String[1];\r
+               }\r
+               String msgId;\r
+               switch(status) {\r
+                       case 202:\r
+                       case ERR_ActionNotCompleted:\r
+                               msgId = "SVC1202";\r
+                               detail[0] = "Accepted, Action not complete";\r
+                               response.setStatus(/*httpstatus=*/202);\r
+                               break;\r
+\r
+                       case 403:\r
+                       case ERR_Policy:\r
+                       case ERR_Security:\r
+                       case ERR_Denied:\r
+                               msgId = "SVC1403";\r
+                               detail[0] = "Forbidden";\r
+                               response.setStatus(/*httpstatus=*/403);\r
+                               break;\r
+                               \r
+                       case 404:\r
+                       case ERR_NotFound:\r
+                               msgId = "SVC1404";\r
+                               detail[0] = "Not Found";\r
+                               response.setStatus(/*httpstatus=*/404);\r
+                               break;\r
+\r
+                       case 406:\r
+                       case ERR_BadData:\r
+                               msgId="SVC1406";\r
+                               detail[0] = "Not Acceptable";\r
+                               response.setStatus(/*httpstatus=*/406);\r
+                               break;\r
+                               \r
+                       case 409:\r
+                       case ERR_ConflictAlreadyExists:\r
+                               msgId = "SVC1409";\r
+                               detail[0] = "Conflict Already Exists";\r
+                               response.setStatus(/*httpstatus=*/409);\r
+                               break;\r
+                       \r
+                       case 501:\r
+                       case ERR_NotImplemented:\r
+                               msgId = "SVC1501";\r
+                               detail[0] = "Not Implemented"; \r
+                               response.setStatus(/*httpstatus=*/501);\r
+                               break;\r
+                               \r
+\r
+                       default:\r
+                               msgId = "SVC1500";\r
+                               detail[0] = "General Service Error";\r
+                               response.setStatus(/*httpstatus=*/500);\r
+                               break;\r
+               }\r
+\r
+               try {\r
+                       StringBuilder holder = new StringBuilder();\r
+                       errDF.newData(trans).load(\r
+                               mapper().errorFromMessage(holder,msgId,msg,detail)).to(response.getOutputStream());\r
+                       trans.checkpoint(\r
+                                       "ErrResp [" + \r
+                                       msgId +\r
+                                       "] " +\r
+                                       holder.toString(),\r
+                                       Env.ALWAYS);\r
+               } catch (Exception e) {\r
+                       trans.error().log(e,"unable to send response for",msg);\r
+               }\r
+       }\r
+       \r
+       /* (non-Javadoc)\r
+        * @see com.att.authz.facade.AuthzFacade#getAPI(org.onap.aaf.authz.env.AuthzTrans, javax.servlet.http.HttpServletResponse)\r
+        */\r
+       public final static String API_REPORT = "apiReport";\r
+       @Override\r
+       public Result<Void> getAPI(AuthzTrans trans, HttpServletResponse resp, RServlet<AuthzTrans> rservlet) {\r
+               TimeTaken tt = trans.start(API_REPORT, Env.SUB);\r
+               try {\r
+                       Api api = new Api();\r
+                       Api.Route ar;\r
+                       Method[] meths = GwServiceImpl.class.getDeclaredMethods();\r
+                       for(RouteReport rr : rservlet.routeReport()) {\r
+                               api.getRoute().add(ar = new Api.Route());\r
+                               ar.setMeth(rr.meth.name());\r
+                               ar.setPath(rr.path);\r
+                               ar.setDesc(rr.desc);\r
+                               ar.getContentType().addAll(rr.contextTypes);\r
+                               for(Method m : meths) {\r
+                                       ApiDoc ad;\r
+                                       if((ad = m.getAnnotation(ApiDoc.class))!=null &&\r
+                                                       rr.meth.equals(ad.method()) &&\r
+                                                   rr.path.equals(ad.path())) {\r
+                                               for(String param : ad.params()) {\r
+                                                       ar.getParam().add(param);\r
+                                               }\r
+                                               for(String text : ad.text()) {\r
+                                                       ar.getComments().add(text);\r
+                                               }\r
+                                               ar.setExpected(ad.expectedCode());\r
+                                               for(int ec : ad.errorCodes()) {\r
+                                                       ar.getExplicitErr().add(ec);\r
+                                               }\r
+                                       }\r
+                               }\r
+                       }\r
+                       apiDF.newData(trans).load(api).to(resp.getOutputStream());\r
+                       setContentType(resp,apiDF.getOutType());\r
+                       return Result.ok();\r
+\r
+               } catch (Exception e) {\r
+                       trans.error().log(e,IN,API_REPORT);\r
+                       return Result.err(e);\r
+               } finally {\r
+                       tt.done();\r
+               }\r
+       }\r
+       \r
+       public final static String API_EXAMPLE = "apiExample";\r
+       /* (non-Javadoc)\r
+        * @see com.att.authz.facade.AuthzFacade#getAPIExample(org.onap.aaf.authz.env.AuthzTrans, javax.servlet.http.HttpServletResponse, java.lang.String)\r
+        */\r
+       @Override\r
+       public Result<Void> getAPIExample(AuthzTrans trans, HttpServletResponse resp, String nameOrContentType, boolean optional) {\r
+               TimeTaken tt = trans.start(API_EXAMPLE, Env.SUB);\r
+               try {\r
+                       String content =Examples.print(apiDF.getEnv(), nameOrContentType, optional); \r
+                       resp.getOutputStream().print(content);\r
+                       setContentType(resp,content.contains("<?xml")?TYPE.XML:TYPE.JSON);\r
+                       return Result.ok();\r
+               } catch (Exception e) {\r
+                       trans.error().log(e,IN,API_EXAMPLE);\r
+                       return Result.err(Result.ERR_NotImplemented,e.getMessage());\r
+               } finally {\r
+                       tt.done();\r
+               }\r
+       }\r
+\r
+}\r