2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
7 * Modifications Copyright (C) 2019 IBM.
8 * ================================================================================
9 * Licensed under the Apache License, Version 2.0 (the "License");
10 * you may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
13 * http://www.apache.org/licenses/LICENSE-2.0
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
20 * ============LICENSE_END=========================================================
23 package org.onap.dmaap.dbcapi.service;
25 import org.onap.dmaap.dbcapi.util.RandomInteger;
27 import java.util.ArrayList;
28 import java.util.List;
31 import javax.ws.rs.core.Response.Status;
33 import org.apache.log4j.Logger;
34 import org.onap.dmaap.dbcapi.client.DrProvConnection;
35 import org.onap.dmaap.dbcapi.database.DatabaseClass;
36 import org.onap.dmaap.dbcapi.logging.BaseLoggingClass;
37 import org.onap.dmaap.dbcapi.model.ApiError;
38 import org.onap.dmaap.dbcapi.model.DR_Pub;
39 import org.onap.dmaap.dbcapi.model.DR_Sub;
40 import org.onap.dmaap.dbcapi.model.Feed;
41 import org.onap.dmaap.dbcapi.model.DmaapObject.DmaapObject_Status;
42 import org.onap.dmaap.dbcapi.util.DmaapConfig;
44 public class FeedService extends BaseLoggingClass {
46 private Map<String, Feed> feeds = DatabaseClass.getFeeds();
47 private DR_PubService pubService = new DR_PubService();
48 private DR_SubService subService = new DR_SubService();
49 private DcaeLocationService dcaeLocations = new DcaeLocationService();
50 private String deleteHandling;
51 private String unit_test;
53 public FeedService() {
54 logger.info( "new FeedService");
55 DmaapConfig p = (DmaapConfig)DmaapConfig.getConfig();
56 deleteHandling = p.getProperty("Feed.deleteHandling", "DeleteOnDR");
57 unit_test = p.getProperty( "UnitTest", "No" );
61 public Map<String, Feed> getFeeds() {
65 private void getSubObjects( Feed f ) {
66 ArrayList<DR_Pub> pubs = pubService.getDr_PubsByFeedId( f.getFeedId() );
68 ArrayList<DR_Sub> subs = subService.getDr_SubsByFeedId( f.getFeedId() );
72 public List<Feed> getAllFeeds( String name, String ver, String match ) {
73 logger.info( "getAllFeeds: name=" + name + " ver=" + ver + " match=" + match);
74 ArrayList<Feed> fatFeeds = new ArrayList<Feed>();
75 for( Feed f: feeds.values() ) {
78 if ( match != null && "startsWith".equals(match) ) {
79 if ( ! f.getFeedName().startsWith( name ) ) {
80 logger.info( "getAllFeeds: feedName=" + f.getFeedName() + " doesn't start with=" + name);
83 } else if ( match != null && match.equals("contains") ) {
84 if ( ! f.getFeedName().contains( name ) ) {
85 logger.info( "getAllFeeds: feedName=" + f.getFeedName() + " doesn't contain=" + name);
89 if ( ! f.getFeedName().equals( name ) ) {
90 logger.info( "getAllFeeds: feedName=" + f.getFeedName() + " doesn't equal=" + name);
96 if ( keep && ver != null ) {
97 if ( ! f.getFeedVersion().equals(ver)) {
98 logger.info( "getAllFeeds: feedVersion=" + f.getFeedName() + " doesn't match " + ver);
101 logger.info( "getAllFeeds: feedVersion=" + f.getFeedName() + " matches " + ver);
114 private Feed _getFeed( String key, ApiError err, boolean flag ) {
115 Feed f = feeds.get( key );
116 if ( f != null && ( flag || f.getStatus() != DmaapObject_Status.DELETED ) ) {
119 err.setCode(Status.NOT_FOUND.getStatusCode());
120 err.setMessage("feed not found");
121 err.setFields("feedId=" + key );
127 public Feed getFeed( String key, ApiError err ) {
128 return _getFeed( key, err, false );
130 public Feed getFeedPure( String key, ApiError err ) {
131 return _getFeed( key, err, true );
134 public Feed getFeedByName( String name, String ver, ApiError err ) {
135 for( Feed f: feeds.values() ) {
136 if ( f.getFeedName().equals( name ) && f.getFeedVersion().equals(ver) ) {
142 err.setCode(Status.NOT_FOUND.getStatusCode());
143 err.setMessage("feed not found");
144 err.setFields("feedName=" + name + " and ver=" + ver );
149 private boolean savePubs( Feed f ) {
150 return savePubs( f, f );
152 // need to save the Pub objects independently and copy pubId from original request
153 private boolean savePubs( Feed fnew, Feed req ) {
155 DR_PubService pubSvc = new DR_PubService();
156 ArrayList<DR_Pub> reqPubs = req.getPubs();
157 ArrayList<DR_Pub> newPubs = fnew.getPubs();
161 int nSize = newPubs.size();
162 int rSize = reqPubs.size();
163 logger.info( "reqPubs size=" + rSize + " newPubs size=" + nSize );
164 if ( nSize != rSize ) {
165 errorLogger.error( "Resulting set of publishers do not match requested set of publishers " + nSize + " vs " + rSize );
166 fnew.setStatus( DmaapObject_Status.INVALID);
169 // NOTE: when i > 1 newPubs are in reverse order from reqPubs
170 for( int i = 0; i < reqPubs.size(); i++ ) {
171 DR_Pub reqPub = reqPubs.get(i);
172 ApiError err = new ApiError();
173 if ( pubSvc.getDr_Pub( reqPub.getPubId(), err ) == null ) {
174 DR_Pub newPub = newPubs.get(nSize - i - 1);
175 reqPub.setPubId(newPub.getPubId());
176 reqPub.setFeedId(newPub.getFeedId());
177 reqPub.setStatus(DmaapObject_Status.VALID);
178 if ( reqPub.getDcaeLocationName() == null ) {
179 reqPub.setDcaeLocationName("notSpecified");
181 pubSvc.addDr_Pub( reqPub );
186 fnew.setPubs(reqPubs);
187 fnew.setStatus(DmaapObject_Status.VALID);
192 private boolean saveSubs( Feed f ) {
193 return saveSubs( f, f );
195 // need to save the Sub objects independently
196 private boolean saveSubs( Feed fnew, Feed req ) {
197 ArrayList<DR_Sub> subs = req.getSubs();
198 if ( subs == null || subs.size() == 0 ) {
199 logger.info( "No subs specified");
201 DR_SubService subSvc = new DR_SubService( fnew.getSubscribeURL() );
202 ApiError err = new ApiError();
203 for( int i = 0; i < subs.size(); i++ ) {
204 DR_Sub sub = subs.get(i);
205 if ( subSvc.getDr_Sub( sub.getSubId(), err) == null ) {
206 subs.set( i, subSvc.addDr_Sub(sub, err));
207 if ( ! err.is2xx()) {
208 logger.error( "i=" + i + " url=" + sub.getDeliveryURL() + " err=" + err.getCode() );
218 fnew.setStatus(DmaapObject_Status.VALID);
223 public Feed addFeed( Feed req, ApiError err ) {
225 // at least 1 pub is required by DR, so create a default pub if none is specified
226 if ( req.getPubs().size() == 0 ) {
227 logger.info( "No pubs specified - creating tmp pub");
228 ArrayList<DR_Pub> pubs = new ArrayList<DR_Pub>();
229 pubs.add( new DR_Pub( dcaeLocations.getCentralLocation())
231 .setRandomPassword());
236 DrProvConnection prov = new DrProvConnection();
237 prov.makeFeedConnection();
238 String resp = prov.doPostFeed( req, err );
239 if ( unit_test.equals( "Yes" ) ) {
240 // assume resp is null, so need to simulate it
241 resp = simulateResp( req, "POST" );
243 logger.info( "resp=" + resp );
244 if ( resp == null ) {
245 switch( err.getCode() ) {
247 err.setFields( "feedName=" + req.getFeedName() + " + feedVersion=" + req.getFeedVersion() );
251 err.setMessage("API deployment/configuration error - contact support");
252 err.setFields( "PROV_AUTH_ADDRESSES");
253 logger.error( "Prov response: 403. " + err.getMessage() + " regarding " + err.getFields() );
257 err.setMessage( "Unexpected response from DR backend" );
258 err.setFields("response");
265 Feed fnew = new Feed( resp );
266 logger.info( "fnew status is:" + fnew.getStatus() );
267 if ( ! fnew.isStatusValid()) {
269 err.setMessage( "Unexpected response from DR backend" );
270 err.setFields("response");
274 //saveChildren( fnew, req );
275 if ( ! savePubs( fnew, req ) || ! saveSubs( fnew, req ) ) {
276 err.setCode(Status.BAD_REQUEST.getStatusCode());
277 err.setMessage("Unable to save Pub or Sub objects");
280 fnew.setFormatUuid(req.getFormatUuid());
282 feeds.put( fnew.getFeedId(), fnew );
286 public Feed updateFeed( Feed req, ApiError err ) {
288 // at least 1 pub is required by DR, so create a default pub if none is specified
289 if ( req.getPubs().size() == 0 ) {
290 logger.info( "No pubs specified - creating tmp pub");
291 ArrayList<DR_Pub> pubs = new ArrayList<DR_Pub>();
292 pubs.add( new DR_Pub( dcaeLocations.getCentralLocation())
294 .setRandomPassword());
298 DrProvConnection prov = new DrProvConnection();
299 prov.makeFeedConnection( req.getFeedId() );
300 String resp = prov.doPutFeed( req, err );
301 if ( unit_test.equals( "Yes" ) ) {
302 // assume resp is null, so need to simulate it
303 resp = simulateResp( req, "PUT" );
306 logger.info( "resp=" + resp );
307 if ( resp == null ) {
308 switch( err.getCode() ) {
310 err.setFields( "feedName=" + req.getFeedName() + " + feedVersion=" + req.getFeedVersion() );
314 err.setMessage("API deployment/configuration error - contact support");
315 err.setFields( "PROV_AUTH_ADDRESSES");
319 err.setMessage( "Unexpected response from DR backend" );
320 err.setFields("response");
326 Feed fnew = new Feed( resp );
327 logger.info( "fnew status is:" + fnew.getStatus() );
328 if ( ! fnew.isStatusValid()) {
330 err.setMessage( "Unexpected response from DR backend" );
331 err.setFields("response");
335 if ( ! savePubs( fnew, req ) || ! saveSubs( fnew, req ) ) {
336 err.setCode(Status.BAD_REQUEST.getStatusCode());
337 err.setMessage("Unable to save Pub or Sub objects");
340 fnew.setFormatUuid(req.getFormatUuid());
342 feeds.put( fnew.getFeedId(), fnew );
348 // DR does not actually delete a feed, so we provide two behaviors:
349 // 1) clean up the feed by removing all subs and pubs, mark it here as DELETED.
350 // then client can add it back if desired.
351 // 2) Call the DR Delete function. Feed with the same name and version can never be added again
353 public Feed removeFeed( Feed req, ApiError err ) {
355 // strip pubs and subs from feed first no matter what
356 ArrayList<DR_Pub> pubs = pubService.getDr_PubsByFeedId( req.getFeedId() );
357 for( DR_Pub pub: pubs ) {
358 pubService.removeDr_Pub(pub.getPubId(), err);
359 if ( ! err.is2xx()) {
363 ArrayList<DR_Sub> subs = subService.getDr_SubsByFeedId( req.getFeedId() );
364 for ( DR_Sub sub: subs ) {
365 subService.removeDr_Sub(sub.getSubId(), err);
366 if ( ! err.is2xx()) {
371 if ( deleteHandling.equalsIgnoreCase("DeleteOnDR")) {
372 DrProvConnection prov = new DrProvConnection();
373 prov.makeFeedConnection( req.getFeedId() );
374 String resp = prov.doDeleteFeed( req, err );
375 if ( unit_test.equals( "Yes" ) ) {
376 // assume resp is null, so need to simulate it
377 resp = simulateDelResp( req );
379 logger.info( "resp=" + resp );
380 if ( resp == null ) {
381 switch( err.getCode() ) {
383 err.setFields( "feedName=" + req.getFeedName() + " + feedVersion=" + req.getFeedVersion() );
387 err.setMessage("API deployment/configuration error - contact support");
388 err.setFields( "PROV_AUTH_ADDRESSES");
392 err.setMessage( "Unexpected response from DR backend" );
393 err.setFields("response");
395 return req; // return back the requested feed - implies it wasn't removed
397 return feeds.remove(req.getFeedId());
400 logger.info( "Disable pubs for deleted feed - creating tmp pub");
401 ArrayList<DR_Pub> tmppub = new ArrayList<DR_Pub>();
402 tmppub.add( new DR_Pub( dcaeLocations.getCentralLocation())
404 .setRandomPassword());
407 Feed fnew = updateFeed( req, err );
408 if ( ! err.is2xx()) {
411 fnew.setStatus(DmaapObject_Status.DELETED);
412 feeds.put( fnew.getFeedId(), fnew );
419 private String simulateResp( Feed f, String action ){
420 String server = "localhost";
422 if ( action.equals( "POST" ) ) {
423 RandomInteger ran = new RandomInteger(10000);
424 feedid = Integer.toString( ran.next() );
425 } else if ( action.equals( "PUT" ) ) {
426 feedid = f.getFeedId();
430 String ret = String.format(
431 "{\"suspend\":false,\"groupid\":0,\"description\":\"%s\",\"version\":\"1.0\",\"authorization\":",
432 f.getFeedDescription() );
434 String endpoints = "{\"endpoint_addrs\":[],\"classification\":\"unclassified\",\"endpoint_ids\":[";
436 for( DR_Pub pub: f.getPubs()) {
437 endpoints += String.format( "%s{\"password\":\"%s\",\"id\":\"%s\"}",
438 sep, pub.getUserpwd(), pub.getUsername() );
445 ret += String.format(
446 "\"name\":\"%s\",\"business_description\":\"\",\"publisher\":\"sim\",\"links\":{\"subscribe\":\"https://%s/subscribe/%s\",\"log\":\"https://%s/feedlog/%s\",\"publish\":\"https://%s/publish/%s\",\"self\":\"https://%s/feed/%s\"}}",
454 logger.info( "simulateResp ret=" + ret );
457 private String simulateDelResp( Feed f ){
458 String server = "localhost";
459 String feedid = f.getFeedId();
460 String ret = String.format(
461 "{\"suspend\":true,\"groupid\":0,\"description\":\"%s\",\"version\":\"1.0\",\"authorization\":{\"endpoint_addrs\":[],\"classification\":\"unclassified\",\"endpoint_ids\":[{\"password\":\"topSecret123\",\"id\":\"sim\"}]},\"name\":\"%s\",\"business_description\":\"\",\"publisher\":\"sim\",\"links\":{\"subscribe\":\"https://%s/subscribe/%s\",\"log\":\"https://%s/feedlog/%s\",\"publish\":\"https://%s/publish/%s\",\"self\":\"https://%s/feed/%s\"}}",
462 f.getFeedDescription(),