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