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