[DMAAP-48] Initial code import
[dmaap/datarouter.git] / datarouter-prov / src / main / java / com / att / research / datarouter / provisioning / SubscribeServlet.java
1 /*******************************************************************************\r
2  * ============LICENSE_START==================================================\r
3  * * org.onap.dmaap\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
10  * * \r
11  *  *      http://www.apache.org/licenses/LICENSE-2.0\r
12  * * \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
19  * *\r
20  * * ECOMP is a trademark and service mark of AT&T Intellectual Property.\r
21  * *\r
22  ******************************************************************************/\r
23 \r
24 \r
25 package com.att.research.datarouter.provisioning;\r
26 \r
27 import java.io.IOException;\r
28 import java.io.InvalidObjectException;\r
29 import java.util.Collection;\r
30 \r
31 import javax.servlet.http.HttpServletRequest;\r
32 import javax.servlet.http.HttpServletResponse;\r
33 \r
34 import org.json.JSONObject;\r
35 \r
36 import com.att.eelf.configuration.EELFLogger;\r
37 import com.att.eelf.configuration.EELFManager;\r
38 import com.att.research.datarouter.authz.AuthorizationResponse;\r
39 import com.att.research.datarouter.provisioning.beans.EventLogRecord;\r
40 import com.att.research.datarouter.provisioning.beans.Feed;\r
41 import com.att.research.datarouter.provisioning.beans.Subscription;\r
42 import com.att.research.datarouter.provisioning.eelf.EelfMsgs;\r
43 import com.att.research.datarouter.provisioning.utils.JSONUtilities;\r
44 \r
45 /**\r
46  * This servlet handles provisioning for the <subscribeURL> which is generated by the provisioning\r
47  * server to handle the creation and inspection of subscriptions to a specific feed.\r
48  *\r
49  * @author Robert Eby\r
50  * @version $Id$\r
51  */\r
52 @SuppressWarnings("serial")\r
53 public class SubscribeServlet extends ProxyServlet {\r
54         \r
55         //Adding EELF Logger Rally:US664892  \r
56     private static EELFLogger eelflogger = EELFManager.getInstance().getLogger("com.att.research.datarouter.provisioning.SubscribeServlet");\r
57 \r
58         /**\r
59          * DELETE on the <subscribeUrl> -- not supported.\r
60          */\r
61         @Override\r
62         public void doDelete(HttpServletRequest req, HttpServletResponse resp) throws IOException {\r
63                 setIpAndFqdnForEelf("doDelete");\r
64                 eelflogger.info(EelfMsgs.MESSAGE_WITH_BEHALF_AND_SUBID, req.getHeader(BEHALF_HEADER),getIdFromPath(req)+"");\r
65                 String message = "DELETE not allowed for the subscribeURL.";\r
66                 EventLogRecord elr = new EventLogRecord(req);\r
67                 elr.setMessage(message);\r
68                 elr.setResult(HttpServletResponse.SC_METHOD_NOT_ALLOWED);\r
69                 eventlogger.info(elr);\r
70                 resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, message);\r
71         }\r
72         /**\r
73          * GET on the <subscribeUrl> -- get the list of subscriptions to a feed.\r
74          * See the <i>Subscription Collection Query</i> section in the <b>Provisioning API</b>\r
75          * document for details on how this method should be invoked.\r
76          */\r
77         @Override\r
78         public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {\r
79                 setIpAndFqdnForEelf("doGet");\r
80                 eelflogger.info(EelfMsgs.MESSAGE_WITH_BEHALF_AND_SUBID, req.getHeader(BEHALF_HEADER),getIdFromPath(req)+"");\r
81                 EventLogRecord elr = new EventLogRecord(req);\r
82                 String message = isAuthorizedForProvisioning(req);\r
83                 if (message != null) {\r
84                         elr.setMessage(message);\r
85                         elr.setResult(HttpServletResponse.SC_FORBIDDEN);\r
86                         eventlogger.info(elr);\r
87                         resp.sendError(HttpServletResponse.SC_FORBIDDEN, message);\r
88                         return;\r
89                 }\r
90                 if (isProxyServer()) {\r
91                         super.doGet(req, resp);\r
92                         return;\r
93                 }\r
94                 String bhdr = req.getHeader(BEHALF_HEADER);\r
95                 if (bhdr == null) {\r
96                         message = "Missing "+BEHALF_HEADER+" header.";\r
97                         elr.setMessage(message);\r
98                         elr.setResult(HttpServletResponse.SC_BAD_REQUEST);\r
99                         eventlogger.info(elr);\r
100                         resp.sendError(HttpServletResponse.SC_BAD_REQUEST, message);\r
101                         return;\r
102                 }\r
103                 int feedid = getIdFromPath(req);\r
104                 if (feedid < 0) {\r
105                         message = "Missing or bad feed number.";\r
106                         elr.setMessage(message);\r
107                         elr.setResult(HttpServletResponse.SC_BAD_REQUEST);\r
108                         eventlogger.info(elr);\r
109                         resp.sendError(HttpServletResponse.SC_BAD_REQUEST, message);\r
110                         return;\r
111                 }\r
112                 Feed feed = Feed.getFeedById(feedid);\r
113                 if (feed == null || feed.isDeleted()) {\r
114                         message = "Missing or bad feed number.";\r
115                         elr.setMessage(message);\r
116                         elr.setResult(HttpServletResponse.SC_NOT_FOUND);\r
117                         eventlogger.info(elr);\r
118                         resp.sendError(HttpServletResponse.SC_NOT_FOUND, message);\r
119                         return;\r
120                 }\r
121                 // Check with the Authorizer\r
122                 AuthorizationResponse aresp = authz.decide(req);\r
123                 if (! aresp.isAuthorized()) {\r
124                         message = "Policy Engine disallows access.";\r
125                         elr.setMessage(message);\r
126                         elr.setResult(HttpServletResponse.SC_FORBIDDEN);\r
127                         eventlogger.info(elr);\r
128                         resp.sendError(HttpServletResponse.SC_FORBIDDEN, message);\r
129                         return;\r
130                 }\r
131 \r
132                 // Display a list of URLs\r
133                 Collection<String> list = Subscription.getSubscriptionUrlList(feedid);\r
134                 String t = JSONUtilities.createJSONArray(list);\r
135 \r
136                 // send response\r
137                 elr.setResult(HttpServletResponse.SC_OK);\r
138                 eventlogger.info(elr);\r
139                 resp.setStatus(HttpServletResponse.SC_OK);\r
140                 resp.setContentType(SUBLIST_CONTENT_TYPE);\r
141                 resp.getOutputStream().print(t);\r
142         }\r
143         /**\r
144          * PUT on the &lt;subscribeUrl&gt; -- not supported.\r
145          */\r
146         @Override\r
147         public void doPut(HttpServletRequest req, HttpServletResponse resp) throws IOException {\r
148                 setIpAndFqdnForEelf("doPut");\r
149                 eelflogger.info(EelfMsgs.MESSAGE_WITH_BEHALF_AND_SUBID, req.getHeader(BEHALF_HEADER),getIdFromPath(req)+"");\r
150                 String message = "PUT not allowed for the subscribeURL.";\r
151                 EventLogRecord elr = new EventLogRecord(req);\r
152                 elr.setMessage(message);\r
153                 elr.setResult(HttpServletResponse.SC_METHOD_NOT_ALLOWED);\r
154                 eventlogger.info(elr);\r
155                 resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, message);\r
156         }\r
157         /**\r
158          * POST on the &lt;subscribeUrl&gt; -- create a new subscription to a feed.\r
159          * See the <i>Creating a Subscription</i> section in the <b>Provisioning API</b>\r
160          * document for details on how this method should be invoked.\r
161          */\r
162         @Override\r
163         public void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {\r
164                 setIpAndFqdnForEelf("doPost");\r
165                 eelflogger.info(EelfMsgs.MESSAGE_WITH_BEHALF, req.getHeader(BEHALF_HEADER));\r
166                 EventLogRecord elr = new EventLogRecord(req);\r
167                 String message = isAuthorizedForProvisioning(req);\r
168                 if (message != null) {\r
169                         elr.setMessage(message);\r
170                         elr.setResult(HttpServletResponse.SC_FORBIDDEN);\r
171                         eventlogger.info(elr);\r
172                         resp.sendError(HttpServletResponse.SC_FORBIDDEN, message);\r
173                         return;\r
174                 }\r
175                 if (isProxyServer()) {\r
176                         super.doPost(req, resp);\r
177                         return;\r
178                 }\r
179                 String bhdr = req.getHeader(BEHALF_HEADER);\r
180                 if (bhdr == null) {\r
181                         message = "Missing "+BEHALF_HEADER+" header.";\r
182                         elr.setMessage(message);\r
183                         elr.setResult(HttpServletResponse.SC_BAD_REQUEST);\r
184                         eventlogger.info(elr);\r
185                         resp.sendError(HttpServletResponse.SC_BAD_REQUEST, message);\r
186                         return;\r
187                 }\r
188                 int feedid = getIdFromPath(req);\r
189                 if (feedid < 0) {\r
190                         message = "Missing or bad feed number.";\r
191                         elr.setMessage(message);\r
192                         elr.setResult(HttpServletResponse.SC_BAD_REQUEST);\r
193                         eventlogger.info(elr);\r
194                         resp.sendError(HttpServletResponse.SC_BAD_REQUEST, message);\r
195                         return;\r
196                 }\r
197                 Feed feed = Feed.getFeedById(feedid);\r
198                 if (feed == null || feed.isDeleted()) {\r
199                         message = "Missing or bad feed number.";\r
200                         elr.setMessage(message);\r
201                         elr.setResult(HttpServletResponse.SC_NOT_FOUND);\r
202                         eventlogger.info(elr);\r
203                         resp.sendError(HttpServletResponse.SC_NOT_FOUND, message);\r
204                         return;\r
205                 }\r
206                 // Check with the Authorizer\r
207                 AuthorizationResponse aresp = authz.decide(req);\r
208                 if (! aresp.isAuthorized()) {\r
209                         message = "Policy Engine disallows access.";\r
210                         elr.setMessage(message);\r
211                         elr.setResult(HttpServletResponse.SC_FORBIDDEN);\r
212                         eventlogger.info(elr);\r
213                         resp.sendError(HttpServletResponse.SC_FORBIDDEN, message);\r
214                         return;\r
215                 }\r
216 \r
217                 // check content type is SUB_CONTENT_TYPE, version 1.0\r
218                 ContentHeader ch = getContentHeader(req);\r
219                 String ver = ch.getAttribute("version");\r
220                 if (!ch.getType().equals(SUB_BASECONTENT_TYPE) || !(ver.equals("1.0") || ver.equals("2.0"))) {\r
221                         intlogger.debug("Content-type is: "+req.getHeader("Content-Type"));\r
222                         message = "Incorrect content-type";\r
223                         elr.setMessage(message);\r
224                         elr.setResult(HttpServletResponse.SC_UNSUPPORTED_MEDIA_TYPE);\r
225                         eventlogger.info(elr);\r
226                         resp.sendError(HttpServletResponse.SC_UNSUPPORTED_MEDIA_TYPE, message);\r
227                         return;\r
228                 }\r
229                 JSONObject jo = getJSONfromInput(req);\r
230                 if (jo == null) {\r
231                         message = "Badly formed JSON";\r
232                         elr.setMessage(message);\r
233                         elr.setResult(HttpServletResponse.SC_BAD_REQUEST);\r
234                         eventlogger.info(elr);\r
235                         resp.sendError(HttpServletResponse.SC_BAD_REQUEST, message);\r
236                         return;\r
237                 }\r
238                 if (intlogger.isDebugEnabled())\r
239                         intlogger.debug(jo.toString());\r
240                 if (++active_subs > max_subs) {\r
241                         active_subs--;\r
242                         message = "Cannot create subscription; the maximum number of subscriptions has been configured.";\r
243                         elr.setMessage(message);\r
244                         elr.setResult(HttpServletResponse.SC_CONFLICT);\r
245                         eventlogger.info(elr);\r
246                         resp.sendError(HttpServletResponse.SC_CONFLICT, message);\r
247                         return;\r
248                 }\r
249                 Subscription sub = null;\r
250                 try {\r
251                         sub = new Subscription(jo);\r
252                 } catch (InvalidObjectException e) {\r
253                         active_subs--;\r
254                         message = e.getMessage();\r
255                         elr.setMessage(message);\r
256                         elr.setResult(HttpServletResponse.SC_BAD_REQUEST);\r
257                         eventlogger.info(elr);\r
258                         resp.sendError(HttpServletResponse.SC_BAD_REQUEST, message);\r
259                         return;\r
260                 }\r
261                 sub.setFeedid(feedid);\r
262                 sub.setSubscriber(bhdr);        // set from X-ATT-DR-ON-BEHALF-OF header\r
263 \r
264                 // Check if this subscription already exists; not an error (yet), just warn\r
265                 Subscription sub2 = Subscription.getSubscriptionMatching(sub);\r
266                 if (sub2 != null)\r
267                         intlogger.warn("PROV0011 Creating a duplicate subscription: new subid="+sub.getSubid()+", old subid="+sub2.getSubid());\r
268 \r
269                 // Create SUBSCRIPTIONS table entries\r
270                 if (doInsert(sub)) {\r
271                         // send response\r
272                         elr.setResult(HttpServletResponse.SC_CREATED);\r
273                         eventlogger.info(elr);\r
274                         resp.setStatus(HttpServletResponse.SC_CREATED);\r
275                         resp.setContentType(SUBFULL_CONTENT_TYPE);\r
276                         resp.setHeader("Location", sub.getLinks().getSelf());\r
277                         resp.getOutputStream().print(sub.asLimitedJSONObject().toString());\r
278 \r
279                         provisioningDataChanged();\r
280                 } else {\r
281                         // Something went wrong with the INSERT\r
282                         active_subs--;\r
283                         elr.setResult(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);\r
284                         eventlogger.info(elr);\r
285                         resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, DB_PROBLEM_MSG);\r
286                 }\r
287         }\r
288 }\r