diff options
Diffstat (limited to 'src/main')
41 files changed, 2350 insertions, 1431 deletions
diff --git a/src/main/java/org/onap/dmaap/dbcapi/aaf/AafConnection.java b/src/main/java/org/onap/dmaap/dbcapi/aaf/AafConnection.java index e22290a..934e541 100644 --- a/src/main/java/org/onap/dmaap/dbcapi/aaf/AafConnection.java +++ b/src/main/java/org/onap/dmaap/dbcapi/aaf/AafConnection.java @@ -37,8 +37,11 @@ import java.net.UnknownHostException; import java.net.ConnectException; import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.SSLContext; import javax.net.ssl.SSLHandshakeException; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; import org.apache.commons.codec.binary.Base64; import org.onap.dmaap.dbcapi.logging.BaseLoggingClass; import org.onap.dmaap.dbcapi.logging.DmaapbcLogMessageEnum; @@ -129,6 +132,10 @@ public class AafConnection extends BaseLoggingClass { uc.setRequestProperty( "Content-Length", Integer.toString( postData.length )); uc.setUseCaches(false); uc.setDoOutput(true); + + SSLContext sc = SSLContext.getInstance("SSL"); + sc.init(null, trustAllCerts, new java.security.SecureRandom()); + uc.setSSLSocketFactory(sc.getSocketFactory()); OutputStream os = null; @@ -296,6 +303,27 @@ public class AafConnection extends BaseLoggingClass { return rc; } + + private TrustManager[] trustAllCerts = new TrustManager[]{ + new X509TrustManager() { + + @Override + public java.security.cert.X509Certificate[] getAcceptedIssuers() + { + return null; + } + @Override + public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType) + { + //No need to implement. + } + @Override + public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType) + { + //No need to implement. + } + } + }; } diff --git a/src/main/java/org/onap/dmaap/dbcapi/client/DrProvConnection.java b/src/main/java/org/onap/dmaap/dbcapi/client/DrProvConnection.java index 3cb3d67..54fa84e 100644 --- a/src/main/java/org/onap/dmaap/dbcapi/client/DrProvConnection.java +++ b/src/main/java/org/onap/dmaap/dbcapi/client/DrProvConnection.java @@ -48,6 +48,8 @@ public class DrProvConnection extends BaseLoggingClass { private String behalfHeader; private String feedContentType; private String subContentType; + private String unit_test; + private String provURI; private HttpsURLConnection uc; @@ -62,8 +64,10 @@ public class DrProvConnection extends BaseLoggingClass { behalfHeader = p.getProperty( "DR.onBehalfHeader", "X-DMAAP-DR-ON-BEHALF-OF"); feedContentType = p.getProperty( "DR.feedContentType", "application/vnd.dmaap-dr.feed"); subContentType = p.getProperty( "DR.subContentType", "application/vnd.dmaap-dr.subscription"); + provURI = p.getProperty( "DR.ProvisioningURI", "/internal/prov"); logger.info( "provURL=" + provURL + " provApi=" + provApi + " behalfHeader=" + behalfHeader + " feedContentType=" + feedContentType + " subContentType=" + subContentType ); + unit_test = p.getProperty( "UnitTest", "No" ); } @@ -95,6 +99,10 @@ public class DrProvConnection extends BaseLoggingClass { sub, nodep ); return makeConnection( provURL + uri ); } + public boolean makeDumpConnection() { + String url = provURL + provURI; + return makeConnection( url ); + } public boolean makeNodesConnection( String varName ) { String uri = String.format("/internal/api/%s", varName); @@ -122,7 +130,6 @@ public class DrProvConnection extends BaseLoggingClass { return(true); } catch (Exception e) { errorLogger.error( DmaapbcLogMessageEnum.HTTP_CONNECTION_ERROR, pURL, e.getMessage() ); - e.printStackTrace(); return(false); } @@ -214,20 +221,28 @@ public class DrProvConnection extends BaseLoggingClass { err.setCode( 500 ); err.setMessage( "Unable to read response from DR"); } catch (Exception e) { - logger.warn("Unable to read response " ); - e.printStackTrace(); - try { - err.setCode( uc.getResponseCode()); - err.setMessage(uc.getResponseMessage()); - } catch (Exception e2) { - err.setCode( 500 ); - err.setMessage("Unable to determine response message"); - } + if ( unit_test.equals( "Yes" ) ) { + err.setCode(200); + err.setMessage( "simulated response"); + logger.info( "artificial 200 response from doPostFeed because unit_test =" + unit_test ); + } else { + logger.warn("Unable to read response " ); + errorLogger.error("Unable to read response ", e.getMessage()); + try { + err.setCode( uc.getResponseCode()); + err.setMessage(uc.getResponseMessage()); + } catch (Exception e2) { + err.setCode( 500 ); + err.setMessage("Unable to determine response message"); + } + } } finally { try { uc.disconnect(); - } catch ( Exception e ) {} + } catch ( Exception e ) { + logger.error(e.getMessage(), e); + } } return responseBody; @@ -270,9 +285,16 @@ public class DrProvConnection extends BaseLoggingClass { err.setMessage(responsemessage); } } catch (Exception e) { - logger.error("Unable to read response " ); - e.printStackTrace(); - } finally { + if ( unit_test.equals( "Yes" ) ) { + err.setCode(200); + err.setMessage( "simulated response"); + logger.info( "artificial 200 response from doXgressPost because unit_test =" + unit_test ); + } else { + logger.error("Unable to read response " ); + logger.error(e.getMessage(), e); + } + } + finally { try { uc.disconnect(); } catch ( Exception e ) { @@ -316,6 +338,7 @@ public class DrProvConnection extends BaseLoggingClass { // without this, Java will connect multiple times to the server to run the same request uc.setDoOutput(false); } catch (Exception e) { + logger.error(e.getMessage(), e); } } rc = uc.getResponseCode(); @@ -346,12 +369,20 @@ public class DrProvConnection extends BaseLoggingClass { } } catch (Exception e) { - System.err.println("Unable to read response " ); - e.printStackTrace(); - } finally { + if ( unit_test.equals( "Yes" ) ) { + err.setCode(200); + err.setMessage( "simulated response"); + logger.info( "artificial 200 response from doPostDr_Sub because unit_test =" + unit_test ); + } else { + logger.error("Unable to read response ", e.getMessage()); + } + } + finally { try { uc.disconnect(); - } catch ( Exception e ) {} + } catch ( Exception e ) { + logger.error(e.getMessage(), e); + } } return responseBody; @@ -388,6 +419,7 @@ public class DrProvConnection extends BaseLoggingClass { // without this, Java will connect multiple times to the server to run the same request uc.setDoOutput(false); } catch (Exception e) { + logger.error(e.getMessage(), e); } } rc = uc.getResponseCode(); @@ -433,19 +465,28 @@ public class DrProvConnection extends BaseLoggingClass { err.setCode( 500 ); err.setMessage( "Unable to read response from DR"); } catch (Exception e) { - logger.warn("Unable to read response " ); - e.printStackTrace(); + if ( unit_test.equals( "Yes" ) ) { + err.setCode(200); + err.setMessage( "simulated response"); + logger.info( "artificial 200 response from doPutFeed because unit_test =" + unit_test ); + } else { + logger.warn("Unable to read response " ); + logger.error(e.getMessage(), e); + } try { err.setCode( uc.getResponseCode()); err.setMessage(uc.getResponseMessage()); } catch (Exception e2) { err.setCode( 500 ); err.setMessage("Unable to determine response message"); + logger.error(e2.getMessage(), e2); } } finally { try { uc.disconnect(); - } catch ( Exception e ) {} + } catch ( Exception e ) { + logger.error(e.getMessage(), e); + } } return responseBody; } @@ -481,6 +522,7 @@ public class DrProvConnection extends BaseLoggingClass { // without this, Java will connect multiple times to the server to run the same request uc.setDoOutput(false); } catch (Exception e) { + logger.error(e.getMessage(), e); } } rc = uc.getResponseCode(); @@ -514,11 +556,20 @@ public class DrProvConnection extends BaseLoggingClass { errorLogger.error( DmaapbcLogMessageEnum.HTTP_CONNECTION_EXCEPTION, provURL, ce.getMessage() ); err.setCode( 500 ); err.setMessage("Backend connection refused"); + logger.error(ce.getMessage(), ce); } catch (Exception e) { - logger.error("Unable to read response " ); - logger.error(e.getMessage(), e); + if ( unit_test.equals( "Yes" ) ) { + err.setCode(200); + err.setMessage( "simulated response"); + logger.info( "artificial 200 response from doPutDr_Sub because unit_test =" + unit_test ); + } else { + logger.error("Unable to read response " ); + logger.error(e.getMessage(), e); + } } finally { - uc.disconnect(); + if(null != uc){ + uc.disconnect(); + } } return responseBody; @@ -530,40 +581,38 @@ public class DrProvConnection extends BaseLoggingClass { //logger.info( "get fields=" + postData ); String responsemessage = null; String responseBody = null; - logger.info( "templog:doGetNodes at 12.10.14.10" ); try { - logger.info( "templog:doGetNodes at 12.10.14.11" ); uc.setRequestMethod("GET"); int rc = -1; - logger.info( "templog:doGetNodes at 12.10.14.12" ); + try { uc.connect(); - logger.info( "templog:doGetNodes at 12.10.14.13" ); - + } catch (ProtocolException pe) { - logger.info( "templog:doGetNodes at 12.10.14.14" ); + // Rcvd error instead of 100-Continue try { // work around glitch in Java 1.7.0.21 and likely others // without this, Java will connect multiple times to the server to run the same request uc.setDoOutput(false); } catch (Exception e) { + logger.error(e.getMessage(), e); } } - logger.info( "templog:doGetNodes at 12.10.14.15" ); + rc = uc.getResponseCode(); logger.info( "http response code:" + rc ); responsemessage = uc.getResponseMessage(); logger.info( "responsemessage=" + responsemessage ); - logger.info( "templog:doGetNodes at 12.10.14.16" ); + if (responsemessage == null) { - logger.info( "templog:doGetNodes at 12.10.14.17" ); + // work around for glitch in Java 1.7.0.21 and likely others // When Expect: 100 is set and a non-100 response is received, the response message is not set but the response code is String h0 = uc.getHeaderField(0); @@ -575,7 +624,7 @@ public class DrProvConnection extends BaseLoggingClass { } } } - logger.info( "templog:doGetNodes at 12.10.14.18" ); + err.setCode(rc); // may not really be an error, but we save rc if (rc == 200 ) { responseBody = bodyToString( uc.getInputStream() ); @@ -584,21 +633,26 @@ public class DrProvConnection extends BaseLoggingClass { err.setMessage(responsemessage); } - logger.info( "templog:doGetNodes at 12.10.14.19" ); + } catch (ConnectException ce) { - logger.info( "templog:doGetNodes at 12.10.14.20" ); + errorLogger.error( DmaapbcLogMessageEnum.HTTP_CONNECTION_EXCEPTION, provURL, ce.getMessage() ); err.setCode( 500 ); err.setMessage("Backend connection refused"); + logger.error(ce.getMessage(), ce); } catch (Exception e) { - logger.info( "templog:doGetNodes at 12.10.14.21" ); - System.err.println("Unable to read response " ); - e.printStackTrace(); + if ( unit_test.equals( "Yes" ) ) { + err.setCode(200); + err.setMessage( "simulated response"); + logger.info( "artificial 200 response from doGetNodes because unit_test =" + unit_test ); + } else { + logger.error("Unable to read response ", e.getMessage()); + } } finally { - logger.info( "templog:doGetNodes at 12.10.14.22" ); + if ( uc != null ) uc.disconnect(); } - logger.info( "templog:doGetNodes at 12.10.14.23" ); + return responseBody; } @@ -665,8 +719,13 @@ public class DrProvConnection extends BaseLoggingClass { } } catch (Exception e) { - System.err.println("Unable to read response " + e.getMessage() ); - e.printStackTrace(); + if ( unit_test.equals( "Yes" ) ) { + err.setCode(200); + err.setMessage( "simulated response"); + logger.info( "artificial 200 response from doPutNodes because unit_test =" + unit_test ); + } else { + logger.error("Unable to read response ", e.getMessage()); + } } finally { if ( uc != null ) { uc.disconnect(); @@ -706,6 +765,7 @@ public class DrProvConnection extends BaseLoggingClass { // without this, Java will connect multiple times to the server to run the same request uc.setDoOutput(false); } catch (Exception e) { + logger.error(e.getMessage(), e); } } rc = uc.getResponseCode(); @@ -746,24 +806,37 @@ public class DrProvConnection extends BaseLoggingClass { errorLogger.error( DmaapbcLogMessageEnum.HTTP_CONNECTION_EXCEPTION, provURL, ce.getMessage() ); err.setCode( 500 ); err.setMessage("Backend connection refused"); + logger.error(ce.getMessage(), ce); } catch (SocketException se) { errorLogger.error( DmaapbcLogMessageEnum.SOCKET_EXCEPTION, se.getMessage(), "response from Prov server" ); err.setCode( 500 ); err.setMessage( "Unable to read response from DR"); + logger.error(se.getMessage(), se); } catch (Exception e) { - logger.warn("Unable to read response " ); - e.printStackTrace(); - try { - err.setCode( uc.getResponseCode()); - err.setMessage(uc.getResponseMessage()); - } catch (Exception e2) { - err.setCode( 500 ); - err.setMessage("Unable to determine response message"); - } + if ( unit_test.equals( "Yes" ) ) { + err.setCode(200); + err.setMessage( "simulated response"); + logger.info( "artificial 200 response from doDeleteFeed because unit_test =" + unit_test ); + } else { + logger.warn("Unable to read response " ); + logger.error(e.getMessage(), e); + try { + err.setCode( uc.getResponseCode()); + err.setMessage(uc.getResponseMessage()); + } catch (Exception e2) { + err.setCode( 500 ); + err.setMessage("Unable to determine response message"); + logger.error(e2.getMessage(), e2); + } + } } finally { try { - uc.disconnect(); - } catch ( Exception e ) {} + if(uc != null) { + uc.disconnect(); + } + } catch ( Exception e ) { + logger.error(e.getMessage(), e); + } } return responseBody; } @@ -800,6 +873,7 @@ public class DrProvConnection extends BaseLoggingClass { // without this, Java will connect multiple times to the server to run the same request uc.setDoOutput(false); } catch (Exception e) { + logger.error(e.getMessage(), e); } } rc = uc.getResponseCode(); @@ -829,48 +903,176 @@ public class DrProvConnection extends BaseLoggingClass { } } catch (ConnectException ce) { - errorLogger.error( DmaapbcLogMessageEnum.HTTP_CONNECTION_EXCEPTION, provURL, ce.getMessage() ); - err.setCode( 500 ); - err.setMessage("Backend connection refused"); + if ( unit_test.equals( "Yes" ) ) { + err.setCode(200); + err.setMessage( "simulated response"); + logger.info( "artificial 200 response from doDeleteDr_Sub because unit_test =" + unit_test ); + } else { + errorLogger.error( DmaapbcLogMessageEnum.HTTP_CONNECTION_EXCEPTION, provURL, ce.getMessage() ); + err.setCode( 500 ); + err.setMessage("Backend connection refused"); + } } catch (Exception e) { - System.err.println("Unable to read response " ); - e.printStackTrace(); + if ( unit_test.equals( "Yes" ) ) { + err.setCode(200); + err.setMessage( "simulated response"); + logger.info( "artificial 200 response from doDeleteDr_Sub because unit_test =" + unit_test ); + } else { + logger.error("Unable to read response ", e.getMessage()); + } } finally { - uc.disconnect(); + if(uc != null){ + uc.disconnect(); + } } return responseBody; } - /* - public static void main( String[] args ) throws Exception { - PropertyConfigurator.configure("log4j.properties"); - logger.info("Started."); - - RandomInteger ri = new RandomInteger(10000); - //String postJSON = String.format("{\"name\": \"dgl feed %d\", \"version\": \"v1.0\", \"description\": \"dgl feed N for testing\", \"authorization\": { \"classification\": \"unclassified\", \"endpoint_addrs\": [],\"endpoint_ids\": [{\"password\": \"test\",\"id\": \"test\"}]}}", ri.next()) ; - int i = ri.next(); - Feed tst = new Feed( "dgl feed " + i, - "v1.0", - "dgl feed " + i + "for testing", - "TEST", - "unclassified" - ); - ArrayList<DR_Pub> pubs = new ArrayList<DR_Pub>(); - pubs.add( new DR_Pub( "centralLocation" ) ); - tst.setPubs(pubs); - - boolean rc; - DrProvConnection context = new DrProvConnection(); - rc = context.makeFeedConnection(); - logger.info( "makeFeedConnection returns " + rc); - ApiError err = new ApiError(); - if ( rc ) { - String tmp = context.doPostFeed( tst, err ); - logger.info( "doPostFeed returns " + tmp); - } - - } - */ + // add double-quotes around a value + // hope his is easier to read than in-line escaping... + private String dq( String v ) { + return ( "\"" + v + "\""); + } + private String dq( String k, String v) { + return( dq(k) + ":" + dq(v)); + } + private String dqc( String k, String v) { + return( dq(k) + ":" + dq(v) + ","); + } + + private String dumpSimulation() { + logger.info( "enter dumpSimulation()"); + String responseBody = + "{" + + dq("feeds") + ":[" + + "{" + dq( "suspend") + ":false," + + dq( "groupid") + ":0," + + dqc( "description", "Some description" ) + + dqc( "version", "m1.1") + + dq( "authorization") + ":" + + "{" + dq( "endpoint_addrs" ) + ":[]," + + dq( "classification", "unclassified") + + dq( "endpoint_ids") + ":[{" + + dqc( "password", "dradmin" ) + + dq( "id", "dradmin") + + "}]}" + + dq( "last_mod") + ":1553738110000," + + dq( "deleted") + ":false," + + dq( "feedid") + ":1," + + dqc( "name", "Default PM Feed") + + dq( "business_description") + ":\"\"," + + dqc( "publisher", "onap") + + dq( "links") + ":{" + + dqc( "subscribe", "https://dmaap-dr-prov/subscribe/1") + + dqc( "log", "https://dmaap-dr-prov/feedlog/1") + + dqc( "publish", "https://dmaap-dr-prov/publish/1") + + dq( "self", "https:/dmaap-dr-prov/feed/1") + + "}" + + dq( "created_date") + ":1553738110000 }" + + "]," + + dq( "groups") + ":[" + + "]," + + dq( "subscriptions") + ":[" + + "]," + + dq( "ingress") + ":[" + + "]," + + dq( "egress") + ":{" + + "}," + + dq( "routing") + ":[" + + "]," + + "}"; + return responseBody; + } + + public String doGetDump( ApiError err ) { + logger.info( "entry: doGetDump() " ); + + String responsemessage = null; + String responseBody = null; + + try { + + uc.setRequestMethod("GET"); + int rc = -1; + + + try { + uc.connect(); + + + } catch (ProtocolException pe) { + + // Rcvd error instead of 100-Continue + try { + // work around glitch in Java 1.7.0.21 and likely others + // without this, Java will connect multiple times to the server to run the same request + uc.setDoOutput(false); + } catch (Exception e) { + logger.error(e.getMessage(), e); + } + } + + rc = uc.getResponseCode(); + logger.info( "http response code:" + rc ); + responsemessage = uc.getResponseMessage(); + logger.info( "responsemessage=" + responsemessage ); + + + + if (responsemessage == null) { + + // work around for glitch in Java 1.7.0.21 and likely others + // When Expect: 100 is set and a non-100 response is received, the response message is not set but the response code is + String h0 = uc.getHeaderField(0); + if (h0 != null) { + int i = h0.indexOf(' '); + int j = h0.indexOf(' ', i + 1); + if (i != -1 && j != -1) { + responsemessage = h0.substring(j + 1); + } + } + } + + err.setCode(rc); // may not really be an error, but we save rc + if (rc == 200 ) { + responseBody = bodyToString( uc.getInputStream() ); + logger.info( "responseBody=" + responseBody ); + } else { + err.setMessage(responsemessage); + } + + + } catch (ConnectException ce) { + if ( unit_test.equals( "Yes" ) ) { + err.setCode(200); + err.setMessage( "simulated response"); + logger.info( "artificial 200 response from doGetNodes because unit_test =" + unit_test ); + responseBody = dumpSimulation(); + + } else { + errorLogger.error( DmaapbcLogMessageEnum.HTTP_CONNECTION_EXCEPTION, provURL, ce.getMessage() ); + err.setCode( 500 ); + err.setMessage("Backend connection refused"); + logger.error(ce.getMessage(), ce); + } + } catch (Exception e) { + if ( unit_test.equals( "Yes" ) ) { + err.setCode(200); + err.setMessage( "simulated response"); + logger.info( "artificial 200 response from doGetNodes because unit_test =" + unit_test ); + responseBody = dumpSimulation(); + + } else { + logger.error("Unable to read response ", e.getMessage()); + } + } finally { + + if ( uc != null ) uc.disconnect(); + } + + return responseBody; + + } } diff --git a/src/main/java/org/onap/dmaap/dbcapi/client/MrProvConnection.java b/src/main/java/org/onap/dmaap/dbcapi/client/MrProvConnection.java index 51bad4f..2be1b33 100644 --- a/src/main/java/org/onap/dmaap/dbcapi/client/MrProvConnection.java +++ b/src/main/java/org/onap/dmaap/dbcapi/client/MrProvConnection.java @@ -30,137 +30,156 @@ import org.onap.dmaap.dbcapi.model.MR_Cluster; import org.onap.dmaap.dbcapi.model.Topic; import org.onap.dmaap.dbcapi.util.DmaapConfig; +import javax.net.ssl.HostnameVerifier; import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.SSLSession; + import java.io.*; import java.net.*; import java.util.Arrays; public class MrProvConnection extends BaseLoggingClass{ - - private String provURL; - - private HttpURLConnection uc; - - - private String topicMgrCred; - private boolean useAAF; - private String user; - private String encPwd; - - public MrProvConnection() { - String mechIdProperty = "aaf.TopicMgrUser"; - String pwdProperty = "aaf.TopicMgrPassword"; - DmaapConfig p = (DmaapConfig)DmaapConfig.getConfig(); - user = p.getProperty( mechIdProperty, "noMechId@domain.netset.com" ); - encPwd = p.getProperty( pwdProperty, "notSet" ); - useAAF= "true".equalsIgnoreCase(p.getProperty("UseAAF", "false")); - topicMgrCred = getCred(); - - } - - private String getCred( ) { - - - String pwd = ""; - AafDecrypt decryptor = new AafDecrypt(); - pwd = decryptor.decrypt(encPwd); - return user + ":" + pwd; - } - - - public boolean makeTopicConnection( MR_Cluster cluster ) { - logger.info( "connect to cluster: " + cluster.getDcaeLocationName()); - - - provURL = cluster.getTopicProtocol() + "://" + cluster.getFqdn() + ":" + cluster.getTopicPort() + "/topics/create"; - - if ( cluster.getTopicProtocol().equals( "https" ) ) { - return makeSecureConnection( provURL ); - } - return makeConnection( provURL ); - } - - private boolean makeSecureConnection( String pURL ) { - logger.info( "makeConnection to " + pURL ); - - try { - URL u = new URL( pURL ); - uc = (HttpsURLConnection) u.openConnection(); - uc.setInstanceFollowRedirects(false); - logger.info( "open connect to " + pURL ); - return(true); - } catch( UnknownHostException uhe ){ - logger.error( "Caught UnknownHostException for " + pURL); - return(false); + + private String provURL; + + private HttpURLConnection uc; + + + private String topicMgrCred; + private String authMethod; + private String user; + private String encPwd; + private boolean hostnameVerify; + + public MrProvConnection() { + String mechIdProperty = "aaf.TopicMgrUser"; + String pwdProperty = "aaf.TopicMgrPassword"; + DmaapConfig p = (DmaapConfig)DmaapConfig.getConfig(); + user = p.getProperty( mechIdProperty, "noMechId@domain.netset.com" ); + encPwd = p.getProperty( pwdProperty, "notSet" ); + authMethod = p.getProperty("MR.authentication", "none"); + topicMgrCred = getCred(); + hostnameVerify= "true".equalsIgnoreCase(p.getProperty("MR.hostnameVerify", "true")); + + } + + private String getCred( ) { + + + String pwd = ""; + AafDecrypt decryptor = new AafDecrypt(); + pwd = decryptor.decrypt(encPwd); + return user + ":" + pwd; + } + + + public boolean makeTopicConnection( MR_Cluster cluster ) { + logger.info( "connect to cluster: " + cluster.getDcaeLocationName()); + + + provURL = cluster.getTopicProtocol() + "://" + cluster.getFqdn() + ":" + cluster.getTopicPort() + "/topics/create"; + + if ( cluster.getTopicProtocol().equals( "https" ) ) { + return makeSecureConnection( provURL ); + } + return makeConnection( provURL ); + } + + private boolean makeSecureConnection( String pURL ) { + logger.info( "makeConnection to " + pURL ); + + try { + + HostnameVerifier hostnameVerifier = new HostnameVerifier() { + @Override + public boolean verify( String hostname, SSLSession session ) { + return true; + } + + }; + URL u = new URL( pURL ); + uc = (HttpsURLConnection) u.openConnection(); + uc.setInstanceFollowRedirects(false); + if ( ! hostnameVerify ) { + HttpsURLConnection ucs = (HttpsURLConnection) uc; + ucs.setHostnameVerifier(hostnameVerifier); + } + logger.info( "open secure connect to " + pURL ); + return(true); + } catch( UnknownHostException uhe ){ + logger.error( "Caught UnknownHostException for " + pURL); + return(false); } catch (Exception e) { logger.error("Unexpected error during openConnection of " + pURL ); - e.printStackTrace(); + logger.error("Unexpected error during openConnection of ",e ); return(false); } - } - private boolean makeConnection( String pURL ) { - logger.info( "makeConnection to " + pURL ); - - try { - URL u = new URL( pURL ); - uc = (HttpURLConnection) u.openConnection(); - uc.setInstanceFollowRedirects(false); - logger.info( "open connect to " + pURL ); - return(true); - } catch( UnknownHostException uhe ){ - logger.error( "Caught UnknownHostException for " + pURL); - return(false); + } + private boolean makeConnection( String pURL ) { + logger.info( "makeConnection to " + pURL ); + + try { + URL u = new URL( pURL ); + uc = (HttpURLConnection) u.openConnection(); + uc.setInstanceFollowRedirects(false); + + logger.info( "open connect to " + pURL ); + return(true); + } catch( UnknownHostException uhe ){ + logger.error( "Caught UnknownHostException for " + pURL); + return(false); } catch (Exception e) { logger.error("Unexpected error during openConnection of " + pURL ); - e.printStackTrace(); + logger.error("Unexpected error during openConnection of ",e ); return(false); } - } - - static String bodyToString( InputStream is ) { - StringBuilder sb = new StringBuilder(); - BufferedReader br = new BufferedReader( new InputStreamReader(is)); - String line; - try { - while ((line = br.readLine()) != null ) { - sb.append( line ); - } - } catch (IOException ex ) { - errorLogger.error( "IOexception:" + ex); - } - - return sb.toString(); - } - - public String doPostTopic( Topic postTopic, ApiError err ) { - String auth = "Basic " + Base64.encodeBase64String(topicMgrCred.getBytes()); + } + + static String bodyToString( InputStream is ) { + StringBuilder sb = new StringBuilder(); + BufferedReader br = new BufferedReader( new InputStreamReader(is)); + String line; + try { + while ((line = br.readLine()) != null ) { + sb.append( line ); + } + } catch (IOException ex ) { + errorLogger.error( "IOexception:" + ex); + } + + return sb.toString(); + } + + public String doPostTopic( Topic postTopic, ApiError err ) { + String auth = "Basic " + Base64.encodeBase64String(topicMgrCred.getBytes()); - String responsemessage = null; - int rc = -1; + String responsemessage = null; + int rc = -1; - try { - byte[] postData = postTopic.getBytes(); - logger.info( "post fields=" + Arrays.toString(postData)); - - // when not using AAF, do not attempt Basic Authentication - if ( useAAF ) { + try { + byte[] postData = postTopic.getBytes(); + logger.info( "post fields=" + Arrays.toString(postData)); + + if ( authMethod.equalsIgnoreCase("basicAuth") ) { uc.setRequestProperty("Authorization", auth); logger.info( "Authenticating with " + auth ); + } else if ( authMethod.equalsIgnoreCase("cert")) { + logger.error( "MR.authentication set for client certificate. Not supported yet."); } - uc.setRequestMethod("POST"); - uc.setRequestProperty("Content-Type", "application/json"); - uc.setRequestProperty( "charset", "utf-8"); - uc.setRequestProperty( "Content-Length", Integer.toString( postData.length )); - uc.setUseCaches(false); - uc.setDoOutput(true); - OutputStream os = null; + uc.setRequestMethod("POST"); + uc.setRequestProperty("Content-Type", "application/json"); + uc.setRequestProperty( "charset", "utf-8"); + uc.setRequestProperty( "Content-Length", Integer.toString( postData.length )); + uc.setUseCaches(false); + uc.setDoOutput(true); + OutputStream os = null; - - try { + + try { uc.connect(); os = uc.getOutputStream(); os.write( postData ); @@ -174,21 +193,21 @@ public class MrProvConnection extends BaseLoggingClass{ } catch (Exception e) { } } catch ( UnknownHostException uhe ) { - errorLogger.error( DmaapbcLogMessageEnum.UNKNOWN_HOST_EXCEPTION , "Unknown Host Exception" , provURL ); - err.setCode(500); - err.setMessage("Unknown Host Exception"); - err.setFields( uc.getURL().getHost()); - return new String( "500: " + uhe.getMessage()); + errorLogger.error( DmaapbcLogMessageEnum.UNKNOWN_HOST_EXCEPTION , "Unknown Host Exception" , provURL ); + err.setCode(500); + err.setMessage("Unknown Host Exception"); + err.setFields( uc.getURL().getHost()); + return new String( "500: " + uhe.getMessage()); }catch ( ConnectException ce ) { - errorLogger.error( DmaapbcLogMessageEnum.HTTP_CONNECTION_EXCEPTION, provURL, "HTTP Connection Exception" ); - err.setCode(500); - err.setMessage("HTTP Connection Exception"); - err.setFields( uc.getURL().getHost()); - return new String( "500: " + ce.getMessage()); + errorLogger.error( DmaapbcLogMessageEnum.HTTP_CONNECTION_EXCEPTION, provURL, "HTTP Connection Exception" ); + err.setCode(500); + err.setMessage("HTTP Connection Exception"); + err.setFields( uc.getURL().getHost()); + return new String( "500: " + ce.getMessage()); } - rc = uc.getResponseCode(); - logger.info( "http response code:" + rc ); - err.setCode(rc); + rc = uc.getResponseCode(); + logger.info( "http response code:" + rc ); + err.setCode(rc); responsemessage = uc.getResponseMessage(); logger.info( "responsemessage=" + responsemessage ); err.setMessage(responsemessage); @@ -207,29 +226,29 @@ public class MrProvConnection extends BaseLoggingClass{ } } if (rc >= 200 && rc < 300 ) { - String responseBody = null; - responseBody = bodyToString( uc.getInputStream() ); - logger.info( "responseBody=" + responseBody ); - return responseBody; + String responseBody = null; + responseBody = bodyToString( uc.getInputStream() ); + logger.info( "responseBody=" + responseBody ); + return responseBody; } - } catch (Exception e) { - errorLogger.error("Unable to read response " ); + } catch (Exception e) { + errorLogger.error("Unable to read response: " + e.getMessage() ); } - finally { - try { - uc.disconnect(); - } catch ( Exception e ) { - errorLogger.error("Unable to disconnect"); - } - } - return new String( rc +": " + responsemessage ); + finally { + try { + uc.disconnect(); + } catch ( Exception e ) { + errorLogger.error("Unable to disconnect"); + } + } + return new String( rc +": " + responsemessage ); - } - + } + - + } diff --git a/src/main/java/org/onap/dmaap/dbcapi/client/MrTopicConnection.java b/src/main/java/org/onap/dmaap/dbcapi/client/MrTopicConnection.java index a92dbc7..0a5f91a 100644 --- a/src/main/java/org/onap/dmaap/dbcapi/client/MrTopicConnection.java +++ b/src/main/java/org/onap/dmaap/dbcapi/client/MrTopicConnection.java @@ -31,8 +31,10 @@ import java.net.ProtocolException; import java.net.URL; import java.net.HttpURLConnection; +import javax.net.ssl.HostnameVerifier; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLException; +import javax.net.ssl.SSLSession; import org.apache.commons.codec.binary.Base64; import org.onap.dmaap.dbcapi.logging.BaseLoggingClass; @@ -48,14 +50,15 @@ public class MrTopicConnection extends BaseLoggingClass { private String mmProvCred; private String unit_test; - private boolean useAAF; - + private String authMethod; + private boolean hostnameVerify; public MrTopicConnection(String user, String pwd ) { mmProvCred = new String( user + ":" + pwd ); DmaapConfig p = (DmaapConfig)DmaapConfig.getConfig(); unit_test = p.getProperty( "UnitTest", "No" ); - useAAF= "true".equalsIgnoreCase(p.getProperty("UseAAF", "false")); + authMethod = p.getProperty("MR.authentication", "none"); + hostnameVerify= "true".equalsIgnoreCase(p.getProperty("MR.hostnameVerify", "true")); } public boolean makeTopicConnection( MR_Cluster cluster, String topic, String overrideFqdn ) { @@ -71,13 +74,28 @@ public class MrTopicConnection extends BaseLoggingClass { return makeConnection( topicURL ); } + private boolean makeSecureConnection( String pURL ) { logger.info( "makeConnection to " + pURL ); - + try { + HostnameVerifier hostnameVerifier = new HostnameVerifier() { + @Override + public boolean verify( String hostname, SSLSession session ) { + return true; + } + + }; + + URL u = new URL( pURL ); - uc = (HttpsURLConnection) u.openConnection(); + uc = (HttpsURLConnection) u.openConnection(); uc.setInstanceFollowRedirects(false); + if ( ! hostnameVerify ) { + HttpsURLConnection ucs = (HttpsURLConnection) uc; + ucs.setHostnameVerifier(hostnameVerifier); + } + logger.info( "open connection to " + pURL ); return(true); } catch (Exception e) { @@ -128,9 +146,11 @@ public class MrTopicConnection extends BaseLoggingClass { try { byte[] postData = postMessage.getBytes(); logger.info( "post fields=" + postMessage ); - if ( useAAF ) { + if ( authMethod.equalsIgnoreCase("basicAuth") ) { uc.setRequestProperty("Authorization", auth); logger.info( "Authenticating with " + auth ); + } else if ( authMethod.equalsIgnoreCase("cert")) { + logger.error( "MR.authentication set for client certificate. Not supported yet."); } uc.setRequestMethod("POST"); uc.setRequestProperty("Content-Type", "application/json"); diff --git a/src/main/java/org/onap/dmaap/dbcapi/database/ConnectionFactory.java b/src/main/java/org/onap/dmaap/dbcapi/database/ConnectionFactory.java index 0f14e60..e32b8e0 100644 --- a/src/main/java/org/onap/dmaap/dbcapi/database/ConnectionFactory.java +++ b/src/main/java/org/onap/dmaap/dbcapi/database/ConnectionFactory.java @@ -3,6 +3,7 @@ * org.onap.dmaap * ================================================================================ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2019 IBM. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -108,6 +109,7 @@ public class ConnectionFactory { TimeUnit.SECONDS.sleep(seconds); } catch (InterruptedException e) { logger.debug("Waiting interrupted. ", e); + Thread.currentThread().interrupt(); } } } diff --git a/src/main/java/org/onap/dmaap/dbcapi/database/DBMap.java b/src/main/java/org/onap/dmaap/dbcapi/database/DBMap.java index 6f63848..b3282ed 100644 --- a/src/main/java/org/onap/dmaap/dbcapi/database/DBMap.java +++ b/src/main/java/org/onap/dmaap/dbcapi/database/DBMap.java @@ -59,7 +59,7 @@ public class DBMap<C> extends TableHandler<C> implements Map<String, C> { return(2); } public Collection<C> values() { - Collection<C> ret = new Vector<>(); + Collection<C> ret = new ArrayList<>(); for (Map.Entry<String, C> x: list()) { ret.add(x.getValue()); } @@ -110,7 +110,6 @@ public class DBMap<C> extends TableHandler<C> implements Map<String, C> { } catch (Exception e) { throw new DBException(e); } - PreparedStatement ps = null; return((new ConnWrapper<C, C>() { protected C run(C val) throws Exception { ps = c.prepareStatement(insorreplstmt); diff --git a/src/main/java/org/onap/dmaap/dbcapi/database/DatabaseClass.java b/src/main/java/org/onap/dmaap/dbcapi/database/DatabaseClass.java index e2004bd..c853782 100644 --- a/src/main/java/org/onap/dmaap/dbcapi/database/DatabaseClass.java +++ b/src/main/java/org/onap/dmaap/dbcapi/database/DatabaseClass.java @@ -32,201 +32,252 @@ import org.onap.dmaap.dbcapi.util.DmaapConfig; import org.onap.dmaap.dbcapi.util.Singleton; +public class DatabaseClass extends BaseLoggingClass { + private static Singleton<Dmaap> dmaap; + private static Map<String, DcaeLocation> dcaeLocations; + private static Map<String, DR_Node> dr_nodes; + private static Map<String, DR_Pub> dr_pubs; + private static Map<String, DR_Sub> dr_subs; + private static Map<String, MR_Client> mr_clients; + private static Map<String, MR_Cluster> mr_clusters; + private static Map<String, Feed> feeds; + private static Map<String, Topic> topics; + private static Map<String, MirrorMaker> mirrors; -public class DatabaseClass extends BaseLoggingClass { - - private static Singleton<Dmaap> dmaap; - private static Map<String, DcaeLocation> dcaeLocations; - private static Map<String, DR_Node> dr_nodes; - private static Map<String, DR_Pub> dr_pubs; - private static Map<String, DR_Sub> dr_subs; - private static Map<String, MR_Client> mr_clients; - private static Map<String, MR_Cluster> mr_clusters; - private static Map<String, Feed> feeds; - private static Map<String, Topic> topics; - private static Map<String, MirrorMaker> mirrors; - - private static long lastTime = 0L; - - - - private static class MirrorTopicsHandler implements DBFieldHandler.SqlOp { - public Object get(ResultSet rs, int index) throws Exception { - String val = rs.getString(index); - if (val == null) { - return(null); - } - List<String> rv = new ArrayList<>(); - for (String s: val.split(",")) { - rv.add(new String(s)); - } - return(rv); - } - public void set(PreparedStatement ps, int index, Object val) throws Exception { - if (val == null) { - ps.setString(index, null); - return; - } - @SuppressWarnings("unchecked") - List<String> xv = (List<String>)val; - StringBuilder sb = new StringBuilder(); - String sep = ""; - for (Object o: xv) { - String rv = (String)o; - sb.append(sep).append(DBFieldHandler.fesc(rv)); - sep = ","; - } - ps.setString(index, sb.toString()); - } - } - private static class TopicReplicationTypeHandler implements DBFieldHandler.SqlOp { - public Object get(ResultSet rs, int index) throws Exception { - int val = rs.getInt(index); - - return (ReplicationType.valueOf(val)); - } - public void set(PreparedStatement ps, int index, Object val) throws Exception { - if (val == null) { - ps.setInt(index, 0); - return; - } - @SuppressWarnings("unchecked") - ReplicationType rep = (ReplicationType) val; - ps.setInt(index, rep.getValue()); - } - } - public static Singleton<Dmaap> getDmaap() { - return dmaap; - } - - - - public static Map<String, DcaeLocation> getDcaeLocations() { - return dcaeLocations; - } - - public static Map<String, DR_Node> getDr_nodes() { - return dr_nodes; - } - - public static Map<String, DR_Sub> getDr_subs() { - return dr_subs; - } - public static Map<String, DR_Pub> getDr_pubs() { - return dr_pubs; - } - - public static Map<String, MR_Client> getMr_clients() { - return mr_clients; - } - - - public static Map<String, MR_Cluster> getMr_clusters() { - return mr_clusters; - } - - public static Map<String, Feed> getFeeds() { - return feeds; - } - public static Map<String, Topic> getTopics() { - return topics; - } - public static Map<String, MirrorMaker> getMirrorMakers() { - return mirrors; - } - - static { - try { - appLogger.info( "begin static initialization"); - appLogger.info( "initializing dmaap" ); - DmaapConfig p = (DmaapConfig)DmaapConfig.getConfig(); - if ("true".equalsIgnoreCase(p.getProperty("UsePGSQL", "false"))) { - appLogger.info("Data from database"); - try { - LoadSchema.upgrade(); - } catch (Exception e) { - appLogger.warn("Problem updating DB schema", e); - } - try { - dmaap = new DBSingleton<>(Dmaap.class, "dmaap"); - dcaeLocations = new DBMap<>(DcaeLocation.class, "dcae_location", "dcae_location_name"); - dr_nodes = new DBMap<>(DR_Node.class, "dr_node", "fqdn"); - dr_pubs = new DBMap<>(DR_Pub.class, "dr_pub", "pub_id"); - dr_subs = new DBMap<>(DR_Sub.class, "dr_sub", "sub_id"); - mr_clients = new DBMap<>(MR_Client.class, "mr_client", "mr_client_id"); - mr_clusters = new DBMap<>(MR_Cluster.class, "mr_cluster", "dcae_location_name"); - feeds = new DBMap<>(Feed.class, "feed", "feed_id"); - TableHandler.setSpecialCase("topic", "replication_case", new TopicReplicationTypeHandler()); - topics = new DBMap<>(Topic.class, "topic", "fqtn"); - TableHandler.setSpecialCase("mirror_maker", "topics", new MirrorTopicsHandler()); - mirrors = new DBMap<>(MirrorMaker.class, "mirror_maker", "mm_name"); - } catch (Exception e) { - errorLogger.error("Error initializing database access " + e, e); - System.exit(1); - } - } else { - appLogger.info("Data from memory"); - dmaap = new Singleton<Dmaap>() { - private Dmaap dmaap; - public void remove() { - dmaap = null; - } - public void init(Dmaap val) { - if (dmaap == null) { - dmaap = val; - } - } - public Dmaap get() { - return(dmaap); - } - public void update(Dmaap nd) { - dmaap.setVersion(nd.getVersion()); - dmaap.setTopicNsRoot(nd.getTopicNsRoot()); - dmaap.setDmaapName(nd.getDmaapName()); - dmaap.setDrProvUrl(nd.getDrProvUrl()); - dmaap.setBridgeAdminTopic(nd.getBridgeAdminTopic()); - dmaap.setLoggingUrl(nd.getLoggingUrl()); - dmaap.setNodeKey(nd.getNodeKey()); - dmaap.setAccessKeyOwner(nd.getAccessKeyOwner()); - } - }; - dcaeLocations = new HashMap<>(); - dr_nodes = new HashMap<>(); - dr_pubs = new HashMap<>(); - dr_subs = new HashMap<>(); - mr_clients = new HashMap<>(); - mr_clusters = new HashMap<>(); - feeds = new HashMap<>(); - topics = new HashMap<>(); - mirrors = new HashMap<>(); - } - dmaap.init(new Dmaap("0", "", "", "", "", "", "", "")); - // force initial read from DB, if it exists - @SuppressWarnings("unused") - Dmaap dmx = dmaap.get(); - - // old code in this spot would read from properties file as part of init. - // but all those properties are now set via /dmaap API - - } catch (Exception e) { - errorLogger.error("Error", e); - errorLogger.error(DmaapbcLogMessageEnum.DB_UPDATE_ERROR, e.getMessage()); - } - - } - - public static synchronized String getNextClientId() { - - long id = System.currentTimeMillis(); - if ( id <= lastTime ) { - id = lastTime + 1; - } - lastTime = id; - return Long.toString(id); - } - - + private static long lastTime = 0L; + private static DBType databaseType; + + private enum DBType { + PGSQL, MEMORY + } + + public static Singleton<Dmaap> getDmaap() { + return dmaap; + } + + + public static Map<String, DcaeLocation> getDcaeLocations() { + return dcaeLocations; + } + + public static Map<String, DR_Node> getDr_nodes() { + return dr_nodes; + } + + public static Map<String, DR_Sub> getDr_subs() { + return dr_subs; + } + + public static Map<String, DR_Pub> getDr_pubs() { + return dr_pubs; + } + + public static Map<String, MR_Client> getMr_clients() { + return mr_clients; + } + + + public static Map<String, MR_Cluster> getMr_clusters() { + return mr_clusters; + } + + public static Map<String, Feed> getFeeds() { + return feeds; + } + + public static Map<String, Topic> getTopics() { + return topics; + } + + public static Map<String, MirrorMaker> getMirrorMakers() { + return mirrors; + } + + static { + try { + appLogger.info("begin static initialization"); + appLogger.info("initializing dmaap"); + determineDatabaseType(); + + switch (databaseType) { + case PGSQL: + databaseResourceInit(); + break; + case MEMORY: + inMemoryResourceInit(); + break; + } + + dmaap.init(new Dmaap("0", "", "", "", "", "", "", "")); + // force initial read from DB, if it exists + @SuppressWarnings("unused") + Dmaap dmx = dmaap.get(); + + // old code in this spot would read from properties file as part of init. + // but all those properties are now set via /dmaap API + + } catch (Exception e) { + errorLogger.error("Error", e); + errorLogger.error(DmaapbcLogMessageEnum.DB_UPDATE_ERROR, e.getMessage()); + } + + } + + public static synchronized String getNextClientId() { + + long id = System.currentTimeMillis(); + if (id <= lastTime) { + id = lastTime + 1; + } + lastTime = id; + return Long.toString(id); + } + + public static synchronized void clearDatabase() { + switch (databaseType) { + case PGSQL: + try { + initDatabase(); + } catch (Exception e) { + errorLogger.error("Error initializing database access " + e, e); + } + break; + case MEMORY: + initMemoryDatabase(); + break; + } + } + + private static void inMemoryResourceInit() { + appLogger.info("Data from memory"); + dmaap = new Singleton<Dmaap>() { + private Dmaap dmaap; + + public void remove() { + dmaap = null; + } + + public void init(Dmaap val) { + if (dmaap == null) { + dmaap = val; + } + } + + public Dmaap get() { + return (dmaap); + } + + public void update(Dmaap nd) { + dmaap.setVersion(nd.getVersion()); + dmaap.setTopicNsRoot(nd.getTopicNsRoot()); + dmaap.setDmaapName(nd.getDmaapName()); + dmaap.setDrProvUrl(nd.getDrProvUrl()); + dmaap.setBridgeAdminTopic(nd.getBridgeAdminTopic()); + dmaap.setLoggingUrl(nd.getLoggingUrl()); + dmaap.setNodeKey(nd.getNodeKey()); + dmaap.setAccessKeyOwner(nd.getAccessKeyOwner()); + } + }; + initMemoryDatabase(); + } + + private static void databaseResourceInit() { + appLogger.info("Data from database"); + try { + LoadSchema.upgrade(); + } catch (Exception e) { + appLogger.warn("Problem updating DB schema", e); + } + try { + dmaap = new DBSingleton<>(Dmaap.class, "dmaap"); + TableHandler.setSpecialCase("topic", "replication_case", new TopicReplicationTypeHandler()); + TableHandler.setSpecialCase("mirror_maker", "topics", new MirrorTopicsHandler()); + initDatabase(); + } catch (Exception e) { + errorLogger.error("Error initializing database access " + e, e); + System.exit(1); + } + } + + private static class MirrorTopicsHandler implements DBFieldHandler.SqlOp { + + public Object get(ResultSet rs, int index) throws Exception { + String val = rs.getString(index); + if (val == null) { + return (null); + } + List<String> rv = new ArrayList<>(); + for (String s : val.split(",")) { + rv.add(new String(s)); + } + return (rv); + } + + public void set(PreparedStatement ps, int index, Object val) throws Exception { + if (val == null) { + ps.setString(index, null); + return; + } + @SuppressWarnings("unchecked") + List<String> xv = (List<String>) val; + StringBuilder sb = new StringBuilder(); + String sep = ""; + for (Object o : xv) { + String rv = (String) o; + sb.append(sep).append(DBFieldHandler.fesc(rv)); + sep = ","; + } + ps.setString(index, sb.toString()); + } + } + + private static class TopicReplicationTypeHandler implements DBFieldHandler.SqlOp { + + public Object get(ResultSet rs, int index) throws Exception { + int val = rs.getInt(index); + + return (ReplicationType.valueOf(val)); + } + + public void set(PreparedStatement ps, int index, Object val) throws Exception { + if (val == null) { + ps.setInt(index, 0); + return; + } + @SuppressWarnings("unchecked") + ReplicationType rep = (ReplicationType) val; + ps.setInt(index, rep.getValue()); + } + } + + private static void initMemoryDatabase() { + dcaeLocations = new HashMap<>(); + dr_nodes = new HashMap<>(); + dr_pubs = new HashMap<>(); + dr_subs = new HashMap<>(); + mr_clients = new HashMap<>(); + mr_clusters = new HashMap<>(); + feeds = new HashMap<>(); + topics = new HashMap<>(); + mirrors = new HashMap<>(); + } + private static void initDatabase() throws Exception { + dcaeLocations = new DBMap<>(DcaeLocation.class, "dcae_location", "dcae_location_name"); + dr_nodes = new DBMap<>(DR_Node.class, "dr_node", "fqdn"); + dr_pubs = new DBMap<>(DR_Pub.class, "dr_pub", "pub_id"); + dr_subs = new DBMap<>(DR_Sub.class, "dr_sub", "sub_id"); + mr_clients = new DBMap<>(MR_Client.class, "mr_client", "mr_client_id"); + mr_clusters = new DBMap<>(MR_Cluster.class, "mr_cluster", "dcae_location_name"); + feeds = new DBMap<>(Feed.class, "feed", "feed_id"); + topics = new DBMap<>(Topic.class, "topic", "fqtn"); + mirrors = new DBMap<>(MirrorMaker.class, "mirror_maker", "mm_name"); + } + private static void determineDatabaseType() { + DmaapConfig dmaapConfig = (DmaapConfig) DmaapConfig.getConfig(); + String isPgSQLset = dmaapConfig.getProperty("UsePGSQL", "false"); + databaseType = isPgSQLset.equalsIgnoreCase("true") ? DBType.PGSQL : DBType.MEMORY; + } } diff --git a/src/main/java/org/onap/dmaap/dbcapi/model/ApiError.java b/src/main/java/org/onap/dmaap/dbcapi/model/ApiError.java index 8d8e23f..c67e55b 100644 --- a/src/main/java/org/onap/dmaap/dbcapi/model/ApiError.java +++ b/src/main/java/org/onap/dmaap/dbcapi/model/ApiError.java @@ -21,13 +21,29 @@ package org.onap.dmaap.dbcapi.model; import javax.xml.bind.annotation.XmlRootElement; +import java.io.Serializable; +import java.util.Objects; @XmlRootElement -public class ApiError { +public class ApiError implements Serializable { private int code; private String message; private String fields; - + + public ApiError() { + this(0, null, null); + } + + public ApiError(int code, String message) { + this(code, message, null); + } + + public ApiError(int code, String message, String fields) { + this.code = code; + this.message = message; + this.fields = fields; + } + public int getCode() { return code; } @@ -58,4 +74,19 @@ public class ApiError { message = null; fields = null; } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + ApiError apiError = (ApiError) o; + return code == apiError.code && + Objects.equals(message, apiError.message) && + Objects.equals(fields, apiError.fields); + } + + @Override + public int hashCode() { + return Objects.hash(code, message, fields); + } } diff --git a/src/main/java/org/onap/dmaap/dbcapi/model/DR_Node.java b/src/main/java/org/onap/dmaap/dbcapi/model/DR_Node.java index a85f040..4b2ef90 100644 --- a/src/main/java/org/onap/dmaap/dbcapi/model/DR_Node.java +++ b/src/main/java/org/onap/dmaap/dbcapi/model/DR_Node.java @@ -21,6 +21,7 @@ package org.onap.dmaap.dbcapi.model; import javax.xml.bind.annotation.XmlRootElement; +import java.util.Objects; @XmlRootElement public class DR_Node extends DmaapObject { @@ -75,4 +76,19 @@ public class DR_Node extends DmaapObject { this.version = version; } + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + DR_Node dr_node = (DR_Node) o; + return Objects.equals(fqdn, dr_node.fqdn) && + Objects.equals(dcaeLocationName, dr_node.dcaeLocationName) && + Objects.equals(hostName, dr_node.hostName) && + Objects.equals(version, dr_node.version); + } + + @Override + public int hashCode() { + return Objects.hash(fqdn, dcaeLocationName, hostName, version); + } } diff --git a/src/main/java/org/onap/dmaap/dbcapi/model/DR_Pub.java b/src/main/java/org/onap/dmaap/dbcapi/model/DR_Pub.java index 0d146b7..4e64089 100644 --- a/src/main/java/org/onap/dmaap/dbcapi/model/DR_Pub.java +++ b/src/main/java/org/onap/dmaap/dbcapi/model/DR_Pub.java @@ -24,6 +24,8 @@ import javax.xml.bind.annotation.XmlRootElement; import org.onap.dmaap.dbcapi.util.RandomString; +import java.util.Objects; + @XmlRootElement public class DR_Pub extends DmaapObject { @@ -151,5 +153,35 @@ public class DR_Pub extends DmaapObject { return ri.nextString(); } - + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + DR_Pub dr_pub = (DR_Pub) o; + return Objects.equals(dcaeLocationName, dr_pub.dcaeLocationName) && + Objects.equals(username, dr_pub.username) && + Objects.equals(userpwd, dr_pub.userpwd) && + Objects.equals(feedId, dr_pub.feedId) && + Objects.equals(pubId, dr_pub.pubId); + } + + @Override + public int hashCode() { + + return Objects.hash(dcaeLocationName, username, userpwd, feedId, pubId); + } + + @Override + public String toString() { + return "DR_Pub{" + + "dcaeLocationName='" + dcaeLocationName + '\'' + + ", username='" + username + '\'' + + ", userpwd='" + userpwd + '\'' + + ", feedId='" + feedId + '\'' + + ", pubId='" + pubId + '\'' + + ", feedName='" + feedName + '\'' + + ", feedVersion='" + feedVersion + '\'' + + '}'; + } } diff --git a/src/main/java/org/onap/dmaap/dbcapi/model/DR_Sub.java b/src/main/java/org/onap/dmaap/dbcapi/model/DR_Sub.java index 9b6e2d7..90da956 100644 --- a/src/main/java/org/onap/dmaap/dbcapi/model/DR_Sub.java +++ b/src/main/java/org/onap/dmaap/dbcapi/model/DR_Sub.java @@ -45,15 +45,16 @@ public class DR_Sub extends DmaapObject { private boolean guaranteedDelivery; private boolean guaranteedSequence; private boolean privilegedSubscriber; - + private boolean decompress; + // NOTE: the following fields are optional in the API but not stored in the DB + private String feedName; private String feedVersion; - public DR_Sub() { } - + public DR_Sub( String dLN, String uN, String uP, @@ -71,12 +72,12 @@ public class DR_Sub extends DmaapObject { this.setStatus( DmaapObject_Status.NEW ); this.subId = "0"; } - + public DR_Sub ( String json ) { logger.info( "DR_Sub:" + json ); JSONParser parser = new JSONParser(); JSONObject jsonObj; - + try { jsonObj = (JSONObject) parser.parse( json ); } catch ( ParseException pe ) { @@ -87,7 +88,7 @@ public class DR_Sub extends DmaapObject { this.setOwner( (String) jsonObj.get("subscriber")); this.setSuspended( (boolean) jsonObj.get("suspend")); - + try { JSONObject links = (JSONObject) jsonObj.get("links"); String url = (String) links.get("feed"); @@ -97,7 +98,7 @@ public class DR_Sub extends DmaapObject { logger.info( "feedid="+ this.getFeedId() ); this.setLogURL( (String) links.get("log") ); } catch (NullPointerException npe ) { - + } try { this.setGuaranteedDelivery( (boolean) jsonObj.get("guaranteed_delivery")); @@ -114,20 +115,23 @@ public class DR_Sub extends DmaapObject { } catch( NullPointerException npe ) { this.setPrivilegedSubscriber(false); } - + try { + this.setDecompress((boolean) jsonObj.get("decompress")); + } catch( NullPointerException npe ) { + this.setDecompress(false); + } + JSONObject del = (JSONObject) jsonObj.get("delivery"); - this.setDeliveryURL( (String) del.get("url") ); + this.setDeliveryURL( (String) del.get("url") ); this.setUsername( (String) del.get("user")); this.setUserpwd( (String) del.get( "password")); this.setUse100((boolean) del.get( "use100")); - - this.setStatus( DmaapObject_Status.VALID ); logger.info( "new DR_Sub returning"); } - + public String getOwner() { return owner; } @@ -234,8 +238,14 @@ public class DR_Sub extends DmaapObject { public void setPrivilegedSubscriber(boolean privilegedSubscriber) { this.privilegedSubscriber = privilegedSubscriber; } - - + + public boolean isDecompress() { + return decompress; + } + + public void setDecompress(boolean decompressData) { + this.decompress = decompressData; + } public String getFeedName() { return feedName; @@ -260,31 +270,32 @@ public class DR_Sub extends DmaapObject { return toProvJSON().getBytes(StandardCharsets.UTF_8); } // returns the DR_Sub object in JSON that conforms to ONAP DR Prov Server expectations - public String toProvJSON() { + public String toProvJSON() { // this is the original DR API that was contributed to ONAP String postJSON = String.format("{\"suspend\": %s, \"delivery\":" + "{\"url\": \"%s\", \"user\": \"%s\", \"password\": \"%s\", \"use100\": %s }" + ", \"metadataOnly\": %s, \"groupid\": \"%s\", \"follow_redirect\": %s " - + ", \"privilegedSubscriber\": %s " + + ", \"privilegedSubscriber\": %s, \"decompress\": %s " + "}" ,this.suspended ,this.getDeliveryURL() ,this.getUsername() ,this.getUserpwd() - ,this.isUse100() + ,this.isUse100() ,"false" ,"0" ,"true" ,this.isPrivilegedSubscriber() - ); - + ,this.isDecompress() + ); + logger.info( postJSON ); return postJSON; } // returns the DR_Sub object in JSON that conforms to AT&T DR Prov Server expectations // In Jan, 2019, the DR API used internally at AT&T diverged, so this function can be used in // that runtime environment - public String toProvJSONforATT() { + public String toProvJSONforATT() { // in DR 3.0, API v2.1 a new groupid field is added. We are not using this required field so just set it to 0. // we send this regardless of DR Release because older versions of DR seem to safely ignore it // and soon those versions won't be around anyway... @@ -312,15 +323,15 @@ public class DR_Sub extends DmaapObject { ,"true" ,this.isGuaranteedDelivery() ,this.isGuaranteedSequence() - ); - + ); + logger.info( postJSON ); return postJSON; } - + @Override public String toString() { - String rc = String.format ( "DR_Sub: {dcaeLocationName=%s username=%s userpwd=%s feedId=%s deliveryURL=%s logURL=%s subid=%s use100=%s suspended=%s owner=%s}", + return String.format ( "DR_Sub: {dcaeLocationName=%s username=%s userpwd=%s feedId=%s deliveryURL=%s logURL=%s subid=%s use100=%s suspended=%s owner=%s}", dcaeLocationName, username, userpwd, @@ -332,6 +343,49 @@ public class DR_Sub extends DmaapObject { suspended, owner ); - return rc; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + DR_Sub drSub = (DR_Sub) o; + + if (use100 != drSub.use100) { + return false; + } + if (suspended != drSub.suspended) { + return false; + } + if (!dcaeLocationName.equals(drSub.dcaeLocationName)) { + return false; + } + if (!username.equals(drSub.username)) { + return false; + } + if (!userpwd.equals(drSub.userpwd)) { + return false; + } + if (!feedId.equals(drSub.feedId)) { + return false; + } + return subId.equals(drSub.subId); + } + + @Override + public int hashCode() { + int result = dcaeLocationName.hashCode(); + result = 31 * result + username.hashCode(); + result = 31 * result + userpwd.hashCode(); + result = 31 * result + feedId.hashCode(); + result = 31 * result + subId.hashCode(); + result = 31 * result + (use100 ? 1 : 0); + result = 31 * result + (suspended ? 1 : 0); + return result; } } diff --git a/src/main/java/org/onap/dmaap/dbcapi/resources/AAFAuthenticationFilter.java b/src/main/java/org/onap/dmaap/dbcapi/resources/AAFAuthenticationFilter.java new file mode 100644 index 0000000..8739511 --- /dev/null +++ b/src/main/java/org/onap/dmaap/dbcapi/resources/AAFAuthenticationFilter.java @@ -0,0 +1,128 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2019 Nokia Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.dmaap.dbcapi.resources; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import java.io.IOException; +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletResponse; +import org.apache.log4j.Logger; +import org.eclipse.jetty.http.HttpStatus; +import org.onap.aaf.cadi.PropAccess; +import org.onap.aaf.cadi.filter.CadiFilter; +import org.onap.dmaap.dbcapi.model.ApiError; +import org.onap.dmaap.dbcapi.util.DmaapConfig; + +public class AAFAuthenticationFilter implements Filter { + + private static final Logger LOGGER = Logger.getLogger(AAFAuthenticationFilter.class.getName()); + static final String CADI_PROPERTIES = "cadi.properties"; + static final String AAF_AUTHN_FLAG = "UseAAF"; + + private boolean isAafEnabled; + private CadiFilter cadiFilter; + + @Override + public void init(FilterConfig filterConfig) throws ServletException { + DmaapConfig dmaapConfig = getConfig(); + String flag = dmaapConfig.getProperty(AAF_AUTHN_FLAG, "false"); + isAafEnabled = "true".equalsIgnoreCase(flag); + initCadi(dmaapConfig); + } + + + @Override + public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) + throws IOException, ServletException { + + if(isAafEnabled) { + cadiFilter.doFilter(servletRequest, servletResponse, filterChain); + updateResponseBody((HttpServletResponse)servletResponse); + } else { + filterChain.doFilter(servletRequest, servletResponse); + } + } + + private void updateResponseBody(HttpServletResponse httpResponse) + throws IOException { + if(httpResponse.getStatus() == 401) { + String errorMsg = "invalid or no credentials provided"; + LOGGER.error(errorMsg); + httpResponse.setContentType("application/json"); + httpResponse.setCharacterEncoding("UTF-8"); + httpResponse.getWriter().print(buildErrorResponse(errorMsg)); + httpResponse.getWriter().flush(); + } + } + + private String buildErrorResponse(String msg) { + try { + return new ObjectMapper().writeValueAsString(new ApiError(HttpStatus.UNAUTHORIZED_401, msg, "Authentication")); + } catch (JsonProcessingException e) { + LOGGER.warn("Could not serialize response entity: " + e.getMessage()); + return ""; + } + } + + + @Override + public void destroy() { + //nothing to cleanup + } + + private void initCadi(DmaapConfig dmaapConfig) throws ServletException { + if(isAafEnabled) { + try { + String cadiPropertiesFile = dmaapConfig.getProperty(CADI_PROPERTIES); + if(cadiPropertiesFile != null && !cadiPropertiesFile.isEmpty()) { + cadiFilter = new CadiFilter(new PropAccess(cadiPropertiesFile)); + } else { + throw new ServletException("Cannot initialize CADI filter.CADI properties not available."); + } + } catch (ServletException e) { + LOGGER.error("CADI init error :" + e.getMessage()); + throw e; + } + } + } + + DmaapConfig getConfig() { + return (DmaapConfig) DmaapConfig.getConfig(); + } + + //tests only + CadiFilter getCadiFilter() { + return cadiFilter; + } + + void setCadiFilter(CadiFilter cadiFilter) { + this.cadiFilter = cadiFilter; + } + + boolean isAafEnabled() { + return isAafEnabled; + } +} diff --git a/src/main/java/org/onap/dmaap/dbcapi/resources/AAFAuthorizationFilter.java b/src/main/java/org/onap/dmaap/dbcapi/resources/AAFAuthorizationFilter.java new file mode 100644 index 0000000..5bc3dec --- /dev/null +++ b/src/main/java/org/onap/dmaap/dbcapi/resources/AAFAuthorizationFilter.java @@ -0,0 +1,116 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2019 Nokia Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.dmaap.dbcapi.resources; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import java.io.IOException; +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import org.apache.log4j.Logger; +import org.eclipse.jetty.http.HttpStatus; +import org.onap.dmaap.dbcapi.model.ApiError; +import org.onap.dmaap.dbcapi.service.DmaapService; +import org.onap.dmaap.dbcapi.util.DmaapConfig; +import org.onap.dmaap.dbcapi.util.PermissionBuilder; + +public class AAFAuthorizationFilter implements Filter{ + + private static final Logger LOGGER = Logger.getLogger(AAFAuthenticationFilter.class.getName()); + static final String AAF_AUTHZ_FLAG = "UseAAF"; + private boolean isAafEnabled = false; + + private PermissionBuilder permissionBuilder; + + @Override + public void init(FilterConfig filterConfig) throws ServletException { + DmaapConfig dmaapConfig = getConfig(); + isAafEnabled = "true".equalsIgnoreCase(dmaapConfig.getProperty(AAF_AUTHZ_FLAG, "false")); + if(isAafEnabled) { + permissionBuilder = new PermissionBuilder(dmaapConfig, getDmaapService()); + } + } + + @Override + public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) + throws IOException, ServletException { + + if(isAafEnabled) { + HttpServletRequest httpRequest = (HttpServletRequest) servletRequest; + permissionBuilder.updateDmaapInstance(); + String permission = permissionBuilder.buildPermission(httpRequest); + + if (httpRequest.isUserInRole(permission)) { + LOGGER.info("User " + httpRequest.getUserPrincipal().getName() + " has permission " + permission); + filterChain.doFilter(servletRequest, servletResponse); + } else { + String msg = "User " + httpRequest.getUserPrincipal().getName() + " does not have permission " + permission; + LOGGER.error(msg); + ((HttpServletResponse) servletResponse).setStatus(HttpStatus.FORBIDDEN_403); + servletResponse.setContentType("application/json"); + servletResponse.setCharacterEncoding("UTF-8"); + servletResponse.getWriter().print(buildErrorResponse(msg)); + servletResponse.getWriter().flush(); + } + } else { + filterChain.doFilter(servletRequest, servletResponse); + } + } + + @Override + public void destroy() { + //nothing to cleanup + } + + DmaapConfig getConfig() { + return (DmaapConfig) DmaapConfig.getConfig(); + } + + DmaapService getDmaapService() { + return new DmaapService(); + } + + private String buildErrorResponse(String msg) { + try { + return new ObjectMapper().writeValueAsString(new ApiError(HttpStatus.FORBIDDEN_403, msg, "Authorization")); + } catch (JsonProcessingException e) { + LOGGER.warn("Could not serialize response entity: " + e.getMessage()); + return ""; + } + } + + PermissionBuilder getPermissionBuilder() { + return permissionBuilder; + } + + void setPermissionBuilder(PermissionBuilder permissionBuilder) { + this.permissionBuilder = permissionBuilder; + } + + void setAafEnabled(boolean aafEnabled) { + isAafEnabled = aafEnabled; + } +} diff --git a/src/main/java/org/onap/dmaap/dbcapi/resources/AuthorizationFilter.java b/src/main/java/org/onap/dmaap/dbcapi/resources/AuthorizationFilter.java index 9dafb55..3ed5717 100644 --- a/src/main/java/org/onap/dmaap/dbcapi/resources/AuthorizationFilter.java +++ b/src/main/java/org/onap/dmaap/dbcapi/resources/AuthorizationFilter.java @@ -20,44 +20,50 @@ package org.onap.dmaap.dbcapi.resources; -import java.io.IOException; - import javax.ws.rs.container.ContainerRequestContext; import javax.ws.rs.container.ContainerRequestFilter; import org.apache.log4j.Logger; import org.onap.dmaap.dbcapi.authentication.AuthenticationErrorException; import org.onap.dmaap.dbcapi.service.ApiService; +import org.onap.dmaap.dbcapi.util.DmaapConfig; @Authorization public class AuthorizationFilter implements ContainerRequestFilter { - - private Logger logger = Logger.getLogger(AuthorizationFilter.class.getName()); - + + private static final String AAF_FLAG = "UseAAF"; + private final Logger logger = Logger.getLogger(AuthorizationFilter.class.getName()); + private final ResponseBuilder responseBuilder = new ResponseBuilder(); + private final boolean isAafEnabled; + + + public AuthorizationFilter() { + DmaapConfig dmaapConfig = (DmaapConfig) DmaapConfig.getConfig(); + String flag = dmaapConfig.getProperty(AAF_FLAG, "false"); + isAafEnabled = "true".equalsIgnoreCase(flag); + } + @Override - public void filter(ContainerRequestContext requestContext) - throws IOException { - - ApiService apiResp = new ApiService() - .setAuth( requestContext.getHeaderString("Authorization") ) - .setUriPath(requestContext.getUriInfo().getPath()) - .setHttpMethod( requestContext.getMethod() ) - .setRequestId( requestContext.getHeaderString("X-ECOMP-RequestID") ); - - try { - apiResp.checkAuthorization(); - } catch ( AuthenticationErrorException ae ) { - logger.error("Error", ae); - requestContext.abortWith( apiResp.unauthorized( apiResp.getErr().getMessage() ) ); - return ; - } catch ( Exception e ) { - logger.error("Error", e); - requestContext.abortWith( apiResp.unavailable() ); - return; - } - + public void filter(ContainerRequestContext requestContext) { + if(!isAafEnabled) { + ApiService apiResp = new ApiService() + .setAuth(requestContext.getHeaderString("Authorization")) + .setUriPath(requestContext.getUriInfo().getPath()) + .setHttpMethod(requestContext.getMethod()) + .setRequestId(requestContext.getHeaderString("X-ECOMP-RequestID")); + + try { + apiResp.checkAuthorization(); + } catch (AuthenticationErrorException ae) { + logger.error("Error", ae); + requestContext.abortWith(responseBuilder.unauthorized(apiResp.getErr().getMessage())); + } catch (Exception e) { + logger.error("Error", e); + requestContext.abortWith(responseBuilder.unavailable()); + } + } } } diff --git a/src/main/java/org/onap/dmaap/dbcapi/resources/BridgeResource.java b/src/main/java/org/onap/dmaap/dbcapi/resources/BridgeResource.java index 192b63d..299c48f 100644 --- a/src/main/java/org/onap/dmaap/dbcapi/resources/BridgeResource.java +++ b/src/main/java/org/onap/dmaap/dbcapi/resources/BridgeResource.java @@ -32,13 +32,11 @@ import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; -import javax.ws.rs.core.Response.Status; import org.onap.dmaap.dbcapi.logging.BaseLoggingClass; import org.onap.dmaap.dbcapi.model.ApiError; import org.onap.dmaap.dbcapi.model.BrTopic; import org.onap.dmaap.dbcapi.model.MirrorMaker; -import org.onap.dmaap.dbcapi.service.ApiService; import org.onap.dmaap.dbcapi.service.MirrorMakerService; import io.swagger.annotations.Api; @@ -46,6 +44,8 @@ import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiResponse; import io.swagger.annotations.ApiResponses; +import static javax.ws.rs.core.Response.Status.BAD_REQUEST; + @Path("/bridge") @Api( value= "bridge", description = "Endpoint for retreiving MR Bridge metrics" ) @Consumes(MediaType.APPLICATION_JSON) @@ -54,6 +54,7 @@ import io.swagger.annotations.ApiResponses; public class BridgeResource extends BaseLoggingClass { private MirrorMakerService mmService = new MirrorMakerService(); + private ResponseBuilder responseBuilder = new ResponseBuilder(); @GET @ApiOperation( value = "return BrTopic details", @@ -66,10 +67,9 @@ public class BridgeResource extends BaseLoggingClass { }) public Response getBridgedTopics(@QueryParam("mmagent") String mmagent, @QueryParam("detail") Boolean detailFlag ){ - ApiService check = new ApiService(); - + if ( mmagent == null ) { - return check.success(getMMcounts(Boolean.TRUE.equals(detailFlag))); + return responseBuilder.success(getMMcounts(Boolean.TRUE.equals(detailFlag))); } logger.info( "getBridgeTopics():" + " mmagent=" + mmagent); @@ -81,7 +81,7 @@ public class BridgeResource extends BaseLoggingClass { MirrorMaker mm = mmService.getMirrorMaker(mmagent); if ( mm == null ) { - return check.notFound(); + return responseBuilder.notFound(); } brTopic.setTopicCount( mm.getTopicCount() ); @@ -91,16 +91,16 @@ public class BridgeResource extends BaseLoggingClass { logger.info( "topicCount [2 locations]: " + brTopic.getTopicCount() ); - return check.success(brTopic); + return responseBuilder.success(brTopic); } else { logger.info( "getBridgeTopics() detail:" + " mmagent=" + mmagent); // get topics between 2 bridged locations MirrorMaker mm = mmService.getMirrorMaker(mmagent); if ( mm == null ) { - return check.notFound(); + return responseBuilder.notFound(); } - return check.success(mm); + return responseBuilder.success(mm); } } @@ -156,15 +156,13 @@ public class BridgeResource extends BaseLoggingClass { @QueryParam("refresh") Boolean refreshFlag, @QueryParam("split") Boolean splitFlag, MirrorMaker newBridge ){ - ApiService check = new ApiService(); - logger.info( "putBridgeTopics() mmagent:" + mmagent ); if ( mmagent != null ) { // put topics between 2 bridged locations MirrorMaker mm = mmService.getMirrorMaker(mmagent); if ( mm == null ) { - return check.notFound(); + return responseBuilder.notFound(); } if ( splitFlag != null && splitFlag == true ) { @@ -173,24 +171,20 @@ public class BridgeResource extends BaseLoggingClass { logger.info( "setting whitelist from message body containing mmName=" + newBridge.getMmName()); if ( ! mmagent.equals(newBridge.getMmName()) ){ logger.error( "mmagent query param does not match mmName in body"); - check.setCode(Status.BAD_REQUEST.getStatusCode()); - check.setMessage("mmagent query param does not match mmName in body"); - return check.error(); + return responseBuilder.error(new ApiError(BAD_REQUEST.getStatusCode(), + "mmagent query param does not match mmName in body")); } mm.setTopics( newBridge.getTopics() ); } else { logger.info( "refreshing whitelist from memory"); } mmService.updateMirrorMaker(mm); - return check.success(mm); + return responseBuilder.success(mm); } else { - logger.error( "mmagent is required for PUT"); - check.setCode(Status.BAD_REQUEST.getStatusCode()); - check.setMessage("mmagent is required for PUT"); - return check.error(); + return responseBuilder.error(new ApiError(BAD_REQUEST.getStatusCode(), "mmagent is required for PUT")); } } diff --git a/src/main/java/org/onap/dmaap/dbcapi/resources/DR_NodeResource.java b/src/main/java/org/onap/dmaap/dbcapi/resources/DR_NodeResource.java index 8091ac3..f001136 100644 --- a/src/main/java/org/onap/dmaap/dbcapi/resources/DR_NodeResource.java +++ b/src/main/java/org/onap/dmaap/dbcapi/resources/DR_NodeResource.java @@ -38,14 +38,15 @@ import javax.ws.rs.Produces; import javax.ws.rs.core.GenericEntity; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; -import javax.ws.rs.core.Response.Status; import org.onap.dmaap.dbcapi.logging.BaseLoggingClass; import org.onap.dmaap.dbcapi.model.ApiError; import org.onap.dmaap.dbcapi.model.DR_Node; -import org.onap.dmaap.dbcapi.service.ApiService; import org.onap.dmaap.dbcapi.service.DR_NodeService; +import static javax.ws.rs.core.Response.Status.BAD_REQUEST; +import static javax.ws.rs.core.Response.Status.NO_CONTENT; + @Path("/dr_nodes") @Api( value= "dr_nodes", description = "Endpoint for a Data Router Node server" ) @Consumes(MediaType.APPLICATION_JSON) @@ -53,7 +54,9 @@ import org.onap.dmaap.dbcapi.service.DR_NodeService; @Authorization public class DR_NodeResource extends BaseLoggingClass { - DR_NodeService dr_nodeService = new DR_NodeService(); + private DR_NodeService dr_nodeService = new DR_NodeService(); + private ResponseBuilder responseBuilder = new ResponseBuilder(); + private RequiredChecker checker = new RequiredChecker(); @GET @ApiOperation( value = "return DR_Node details", @@ -64,13 +67,11 @@ public class DR_NodeResource extends BaseLoggingClass { @ApiResponse( code = 400, message = "Error", response = ApiError.class ) }) public Response getDr_Nodes() { - ApiService resp = new ApiService(); - List<DR_Node> nodes = dr_nodeService.getAllDr_Nodes(); GenericEntity<List<DR_Node>> list = new GenericEntity<List<DR_Node>>(nodes) { }; - return resp.success(list); + return responseBuilder.success(list); } @POST @@ -81,26 +82,22 @@ public class DR_NodeResource extends BaseLoggingClass { @ApiResponse( code = 200, message = "Success", response = DR_Node.class), @ApiResponse( code = 400, message = "Error", response = ApiError.class ) }) - public Response addDr_Node( - DR_Node node - ) { - ApiService resp = new ApiService(); + public Response addDr_Node(DR_Node node) { + + ApiError apiError = new ApiError(); try { - resp.required( "dcaeLocation", node.getDcaeLocationName(), ""); - resp.required( "fqdn", node.getFqdn(), ""); + checker.required( "dcaeLocation", node.getDcaeLocationName()); + checker.required( "fqdn", node.getFqdn()); } catch ( RequiredFieldException rfe ) { - resp.setCode(Status.BAD_REQUEST.getStatusCode()); - resp.setMessage("missing required field"); - resp.setFields("dcaeLocation, fqdn"); - - return resp.error(); + return responseBuilder.error(new ApiError(BAD_REQUEST.getStatusCode(), + "missing required field", "dcaeLocation, fqdn")); } - DR_Node nNode = dr_nodeService.addDr_Node(node, resp.getErr()); - if ( resp.getErr().is2xx()) { - return resp.success(nNode); + DR_Node nNode = dr_nodeService.addDr_Node(node, apiError); + if (apiError.is2xx()) { + return responseBuilder.success(nNode); } - return resp.error(); + return responseBuilder.error(apiError); } @PUT @@ -112,24 +109,23 @@ public class DR_NodeResource extends BaseLoggingClass { @ApiResponse( code = 400, message = "Error", response = ApiError.class ) }) @Path("/{fqdn}") - public Response updateDr_Node( - @PathParam("fqdn") String name, - DR_Node node - ) { - ApiService resp = new ApiService(); + public Response updateDr_Node(@PathParam("fqdn") String name, DR_Node node) { + + ApiError apiError = new ApiError(); try { - resp.required( "dcaeLocation", name, ""); - resp.required( "fqdn", node.getFqdn(), ""); + checker.required( "dcaeLocation", node.getDcaeLocationName()); + checker.required( "fqdn", node.getFqdn()); } catch ( RequiredFieldException rfe ) { - return resp.error(); + return responseBuilder.error(new ApiError(BAD_REQUEST.getStatusCode(), + "missing required field", "dcaeLocation, fqdn")); } node.setFqdn(name); - DR_Node nNode = dr_nodeService.updateDr_Node(node, resp.getErr()); - if ( resp.getErr().is2xx()) { - return resp.success(nNode); + DR_Node nNode = dr_nodeService.updateDr_Node(node, apiError); + if (apiError.is2xx()) { + return responseBuilder.success(nNode); } - return resp.error(); + return responseBuilder.error(apiError); } @DELETE @@ -142,22 +138,16 @@ public class DR_NodeResource extends BaseLoggingClass { }) @Path("/{fqdn}") public Response deleteDr_Node( - @PathParam("fqdn") String name - ){ + @PathParam("fqdn") String name){ - ApiService resp = new ApiService(); - try { - resp.required( "fqdn", name, ""); - } catch ( RequiredFieldException rfe ) { - logger.debug( resp.toString() ); - return resp.error(); - } - dr_nodeService.removeDr_Node(name, resp.getErr()); - if ( resp.getErr().is2xx() ) { - return resp.success(Status.NO_CONTENT.getStatusCode(), null); + ApiError apiError = new ApiError(); + + dr_nodeService.removeDr_Node(name, apiError); + if (apiError.is2xx()) { + return responseBuilder.success(NO_CONTENT.getStatusCode(), null); } - return resp.error(); + return responseBuilder.error(apiError); } @GET @@ -169,15 +159,14 @@ public class DR_NodeResource extends BaseLoggingClass { @ApiResponse( code = 400, message = "Error", response = ApiError.class ) }) @Path("/{fqdn}") - public Response get( - @PathParam("fqdn") String name - ) { - ApiService resp = new ApiService(); - - DR_Node nNode = dr_nodeService.getDr_Node( name, resp.getErr() ); - if ( resp.getErr().is2xx() ) { - return resp.success(nNode); + public Response get(@PathParam("fqdn") String name) { + + ApiError apiError = new ApiError(); + + DR_Node nNode = dr_nodeService.getDr_Node( name, apiError ); + if (apiError.is2xx()) { + return responseBuilder.success(nNode); } - return resp.error(); + return responseBuilder.error(apiError); } } diff --git a/src/main/java/org/onap/dmaap/dbcapi/resources/DR_PubResource.java b/src/main/java/org/onap/dmaap/dbcapi/resources/DR_PubResource.java index 1673857..6e652a8 100644 --- a/src/main/java/org/onap/dmaap/dbcapi/resources/DR_PubResource.java +++ b/src/main/java/org/onap/dmaap/dbcapi/resources/DR_PubResource.java @@ -46,7 +46,6 @@ import org.onap.dmaap.dbcapi.logging.BaseLoggingClass; import org.onap.dmaap.dbcapi.model.ApiError; import org.onap.dmaap.dbcapi.model.DR_Pub; import org.onap.dmaap.dbcapi.model.Feed; -import org.onap.dmaap.dbcapi.service.ApiService; import org.onap.dmaap.dbcapi.service.DR_PubService; import org.onap.dmaap.dbcapi.service.FeedService; @@ -58,7 +57,9 @@ import org.onap.dmaap.dbcapi.service.FeedService; @Authorization public class DR_PubResource extends BaseLoggingClass { - DR_PubService dr_pubService = new DR_PubService(); + private DR_PubService dr_pubService = new DR_PubService(); + private ResponseBuilder responseBuilder = new ResponseBuilder(); + private RequiredChecker checker = new RequiredChecker(); @GET @ApiOperation( value = "return DR_Pub details", @@ -69,14 +70,12 @@ public class DR_PubResource extends BaseLoggingClass { @ApiResponse( code = 400, message = "Error", response = ApiError.class ) }) public Response getDr_Pubs() { - ApiService resp = new ApiService(); - logger.info( "Entry: GET /dr_pubs"); List<DR_Pub> pubs = dr_pubService.getAllDr_Pubs(); GenericEntity<List<DR_Pub>> list = new GenericEntity<List<DR_Pub>>(pubs) { }; - return resp.success(list); + return responseBuilder.success(list); } @POST @@ -87,47 +86,46 @@ public class DR_PubResource extends BaseLoggingClass { @ApiResponse( code = 200, message = "Success", response = DR_Pub.class), @ApiResponse( code = 400, message = "Error", response = ApiError.class ) }) - public Response addDr_Pub( - DR_Pub pub - ) { - ApiService resp = new ApiService(); + public Response addDr_Pub(DR_Pub pub) { + ApiError apiError = new ApiError(); FeedService feeds = new FeedService(); Feed fnew = null; logger.info( "Entry: POST /dr_pubs"); try { - resp.required( "feedId", pub.getFeedId(), ""); + checker.required( "feedId", pub.getFeedId()); } catch ( RequiredFieldException rfe ) { try { - resp.required( "feedName", pub.getFeedName(), ""); + checker.required( "feedName", pub.getFeedName()); }catch ( RequiredFieldException rfe2 ) { - logger.debug( resp.toString() ); - return resp.error(); + logger.debug( rfe2.getApiError().toString() ); + return responseBuilder.error(rfe2.getApiError()); } // if we found a FeedName instead of a FeedId then try to look it up. List<Feed> nfeeds = feeds.getAllFeeds( pub.getFeedName(), pub.getFeedVersion(), "equals"); - if ( nfeeds.size() != 1 ) { - logger.debug( "Attempt to match "+ pub.getFeedName() + " ver="+pub.getFeedVersion() + " matched " + nfeeds.size() ); - return resp.error(); + if ( nfeeds.isEmpty() ) { + apiError.setCode(Status.NOT_FOUND.getStatusCode()); + apiError.setFields("feedName"); + return responseBuilder.error(apiError); } fnew = nfeeds.get(0); } try { - resp.required( "dcaeLocationName", pub.getDcaeLocationName(), ""); + checker.required( "dcaeLocationName", pub.getDcaeLocationName()); } catch ( RequiredFieldException rfe ) { - logger.debug( resp.getErr().toString() ); - return resp.error(); + logger.debug( rfe.getApiError().toString() ); + return responseBuilder.error(rfe.getApiError()); } // we may have fnew already if located by FeedName if ( fnew == null ) { - fnew = feeds.getFeed( pub.getFeedId(), resp.getErr() ); + fnew = feeds.getFeed(pub.getFeedId(), apiError); } if ( fnew == null ) { logger.info( "Specified feed " + pub.getFeedId() + " or " + pub.getFeedName() + " not known to Bus Controller"); - return resp.error(); + return responseBuilder.error(apiError); } ArrayList<DR_Pub> pubs = fnew.getPubs(); @@ -143,16 +141,16 @@ public class DR_PubResource extends BaseLoggingClass { } pubs.add( pub ); fnew.setPubs(pubs); - fnew = feeds.updateFeed( fnew, resp.getErr() ); + fnew = feeds.updateFeed(fnew, apiError); - if ( ! resp.getErr().is2xx()) { - return resp.error(); + if (!apiError.is2xx()) { + return responseBuilder.error(apiError); } pubs = fnew.getPubs(); logger.info( "num existing pubs after = " + pubs.size() ); - DR_Pub pnew = dr_pubService.getDr_Pub(pub.getPubId(), resp.getErr()); - return resp.success(Status.CREATED.getStatusCode(), pnew); + DR_Pub pnew = dr_pubService.getDr_Pub(pub.getPubId(), apiError); + return responseBuilder.success(Status.CREATED.getStatusCode(), pnew); } @PUT @@ -164,16 +162,11 @@ public class DR_PubResource extends BaseLoggingClass { @ApiResponse( code = 400, message = "Error", response = ApiError.class ) }) @Path("/{pubId}") - public Response updateDr_Pub( - @PathParam("pubId") String name, - DR_Pub pub - ) { - ApiService resp = new ApiService(); - + public Response updateDr_Pub(@PathParam("pubId") String name, DR_Pub pub) { logger.info( "Entry: PUT /dr_pubs"); pub.setPubId(name); DR_Pub res = dr_pubService.updateDr_Pub(pub); - return resp.success(res); + return responseBuilder.success(res); } @DELETE @@ -185,33 +178,31 @@ public class DR_PubResource extends BaseLoggingClass { @ApiResponse( code = 400, message = "Error", response = ApiError.class ) }) @Path("/{pubId}") - public Response deleteDr_Pub( - @PathParam("pubId") String id - ){ + public Response deleteDr_Pub(@PathParam("pubId") String id){ - ApiService resp = new ApiService(); + ApiError apiError = new ApiError(); try { - resp.required( "pubId", id, ""); + checker.required( "pubId", id); } catch ( RequiredFieldException rfe ) { - return resp.error(); + return responseBuilder.error(rfe.getApiError()); } - DR_Pub pub = dr_pubService.getDr_Pub( id, resp.getErr() ); - if ( ! resp.getErr().is2xx()) { - return resp.error(); + DR_Pub pub = dr_pubService.getDr_Pub(id, apiError); + if ( !apiError.is2xx()) { + return responseBuilder.error(apiError); } FeedService feeds = new FeedService(); - Feed fnew = feeds.getFeed( pub.getFeedId(), resp.getErr() ); + Feed fnew = feeds.getFeed(pub.getFeedId(), apiError); if ( fnew == null ) { logger.info( "Specified feed " + pub.getFeedId() + " not known to Bus Controller"); - return resp.error(); + return responseBuilder.error(apiError); } ArrayList<DR_Pub> pubs = fnew.getPubs(); if ( pubs.size() == 1 ) { - resp.setCode(Status.BAD_REQUEST.getStatusCode()); - resp.setMessage( "Can't delete the last publisher of a feed"); - return resp.error(); + apiError.setCode(Status.BAD_REQUEST.getStatusCode()); + apiError.setMessage( "Can't delete the last publisher of a feed"); + return responseBuilder.error(apiError); } for( Iterator<DR_Pub> i = pubs.iterator(); i.hasNext(); ) { @@ -221,16 +212,16 @@ public class DR_PubResource extends BaseLoggingClass { } } fnew.setPubs(pubs); - fnew = feeds.updateFeed( fnew, resp.getErr() ); - if ( ! resp.getErr().is2xx()) { - return resp.error(); + fnew = feeds.updateFeed(fnew,apiError); + if (!apiError.is2xx()) { + return responseBuilder.error(apiError); } - dr_pubService.removeDr_Pub(id, resp.getErr() ); - if ( ! resp.getErr().is2xx()) { - return resp.error(); + dr_pubService.removeDr_Pub(id, apiError); + if (!apiError.is2xx()) { + return responseBuilder.error(apiError); } - return resp.success(Status.NO_CONTENT.getStatusCode(), null); + return responseBuilder.success(Status.NO_CONTENT.getStatusCode(), null); } @GET @@ -242,21 +233,19 @@ public class DR_PubResource extends BaseLoggingClass { @ApiResponse( code = 400, message = "Error", response = ApiError.class ) }) @Path("/{pubId}") - public Response get( - @PathParam("pubId") String id - ) { - ApiService resp = new ApiService(); + public Response get(@PathParam("pubId") String id) { + ApiError apiError = new ApiError(); try { - resp.required( "feedId", id, ""); + checker.required( "feedId", id); } catch ( RequiredFieldException rfe ) { - return resp.error(); + return responseBuilder.error(rfe.getApiError()); } - DR_Pub pub = dr_pubService.getDr_Pub( id, resp.getErr() ); - if ( ! resp.getErr().is2xx()) { - resp.getErr(); + DR_Pub pub = dr_pubService.getDr_Pub(id, apiError); + if (!apiError.is2xx()) { + return responseBuilder.error(apiError); } - return resp.success(Status.OK.getStatusCode(), pub); + return responseBuilder.success(Status.OK.getStatusCode(), pub); } } diff --git a/src/main/java/org/onap/dmaap/dbcapi/resources/DR_SubResource.java b/src/main/java/org/onap/dmaap/dbcapi/resources/DR_SubResource.java index 498454e..2fa6ccd 100644 --- a/src/main/java/org/onap/dmaap/dbcapi/resources/DR_SubResource.java +++ b/src/main/java/org/onap/dmaap/dbcapi/resources/DR_SubResource.java @@ -22,6 +22,7 @@ package org.onap.dmaap.dbcapi.resources; +import com.google.common.collect.Iterables; import java.util.ArrayList; import java.util.List; @@ -42,7 +43,6 @@ import org.onap.dmaap.dbcapi.logging.BaseLoggingClass; import org.onap.dmaap.dbcapi.model.ApiError; import org.onap.dmaap.dbcapi.model.DR_Sub; import org.onap.dmaap.dbcapi.model.Feed; -import org.onap.dmaap.dbcapi.service.ApiService; import org.onap.dmaap.dbcapi.service.DR_SubService; import org.onap.dmaap.dbcapi.service.FeedService; @@ -51,6 +51,8 @@ import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiResponse; import io.swagger.annotations.ApiResponses; +import static javax.ws.rs.core.Response.Status.CREATED; + @Path("/dr_subs") @Api( value= "dr_subs", description = "Endpoint for a Data Router client that implements a Subscriber" ) @@ -58,6 +60,9 @@ import io.swagger.annotations.ApiResponses; @Produces(MediaType.APPLICATION_JSON) @Authorization public class DR_SubResource extends BaseLoggingClass { + + private ResponseBuilder responseBuilder = new ResponseBuilder(); + private RequiredChecker checker = new RequiredChecker(); @GET @ApiOperation( value = "return DR_Sub details", @@ -68,15 +73,12 @@ public class DR_SubResource extends BaseLoggingClass { @ApiResponse( code = 400, message = "Error", response = ApiError.class ) }) public Response getDr_Subs() { - - ApiService resp = new ApiService(); - DR_SubService dr_subService = new DR_SubService(); List<DR_Sub> subs = dr_subService.getAllDr_Subs(); GenericEntity<List<DR_Sub>> list = new GenericEntity<List<DR_Sub>>(subs) { }; - return resp.success(list); + return responseBuilder.success(list); } @POST @@ -87,59 +89,63 @@ public class DR_SubResource extends BaseLoggingClass { @ApiResponse( code = 200, message = "Success", response = DR_Sub.class), @ApiResponse( code = 400, message = "Error", response = ApiError.class ) }) - public Response addDr_Sub( - DR_Sub sub - ) { - - ApiService resp = new ApiService(); + public Response addDr_Sub(DR_Sub sub) { + + ApiError apiError = new ApiError(); FeedService feeds = new FeedService(); Feed fnew = null; try { - resp.required( "feedId", sub.getFeedId(), ""); + checker.required( "feedId", sub.getFeedId()); } catch ( RequiredFieldException rfe ) { try { - resp.required( "feedName", sub.getFeedName(), ""); + checker.required( "feedName", sub.getFeedName()); }catch ( RequiredFieldException rfe2 ) { - logger.debug( resp.toString() ); - return resp.error(); + logger.debug( rfe2.getApiError().toString() ); + return responseBuilder.error(rfe2.getApiError()); } // if we found a FeedName instead of a FeedId then try to look it up. List<Feed> nfeeds = feeds.getAllFeeds( sub.getFeedName(), sub.getFeedVersion(), "equals"); - if ( nfeeds.size() != 1 ) { + if ( nfeeds.isEmpty() ) { + apiError.setCode(Status.NOT_FOUND.getStatusCode()); + apiError.setFields("feedName"); + return responseBuilder.error(apiError); + } else if (nfeeds.size() > 1) { logger.debug( "Attempt to match "+ sub.getFeedName() + " ver="+sub.getFeedVersion() + " matched " + nfeeds.size() ); - return resp.error(); + apiError.setCode(Status.CONFLICT.getStatusCode()); + apiError.setFields("feedName"); + return responseBuilder.error(apiError); } - fnew = nfeeds.get(0); + fnew = Iterables.getOnlyElement(nfeeds); } try { - resp.required( "dcaeLocationName", sub.getDcaeLocationName(), ""); + checker.required( "dcaeLocationName", sub.getDcaeLocationName()); } catch ( RequiredFieldException rfe ) { - logger.debug( resp.toString() ); - return resp.error(); + logger.debug( rfe.getApiError().toString() ); + return responseBuilder.error(rfe.getApiError()); } // we may have fnew already if located by FeedName if ( fnew == null ) { - fnew = feeds.getFeed( sub.getFeedId(), resp.getErr() ); + fnew = feeds.getFeed( sub.getFeedId(), apiError); } if ( fnew == null ) { logger.warn( "Specified feed " + sub.getFeedId() + " or " + sub.getFeedName() + " not known to Bus Controller"); - resp.setCode(Status.NOT_FOUND.getStatusCode()); - return resp.error(); + apiError.setCode(Status.NOT_FOUND.getStatusCode()); + return responseBuilder.error(apiError); } DR_SubService dr_subService = new DR_SubService( fnew.getSubscribeURL()); ArrayList<DR_Sub> subs = fnew.getSubs(); logger.info( "num existing subs before = " + subs.size() ); - DR_Sub snew = dr_subService.addDr_Sub(sub, resp.getErr() ); - if ( ! resp.getErr().is2xx() ) { - return resp.error(); + DR_Sub snew = dr_subService.addDr_Sub(sub, apiError); + if (!apiError.is2xx()) { + return responseBuilder.error(apiError); } subs.add( snew ); logger.info( "num existing subs after = " + subs.size() ); fnew.setSubs(subs); logger.info( "update feed"); - return resp.success(Status.CREATED.getStatusCode(), snew); + return responseBuilder.success(CREATED.getStatusCode(), snew); } @@ -152,36 +158,33 @@ public class DR_SubResource extends BaseLoggingClass { @ApiResponse( code = 400, message = "Error", response = ApiError.class ) }) @Path("/{subId}") - public Response updateDr_Sub( - @PathParam("subId") String name, - DR_Sub sub - ) { + public Response updateDr_Sub(@PathParam("subId") String name, DR_Sub sub) { - ApiService resp = new ApiService(); + ApiError apiError = new ApiError(); try { - resp.required( "subId", name, ""); - resp.required( "feedId", sub.getFeedId(), ""); - resp.required( "dcaeLocationName", sub.getDcaeLocationName(), ""); + checker.required( "subId", name); + checker.required( "feedId", sub.getFeedId()); + checker.required( "dcaeLocationName", sub.getDcaeLocationName()); } catch ( RequiredFieldException rfe ) { - logger.debug( resp.toString() ); - return resp.error(); + logger.debug( rfe.getApiError().toString() ); + return responseBuilder.error(rfe.getApiError()); } FeedService feeds = new FeedService(); - Feed fnew = feeds.getFeed( sub.getFeedId(), resp.getErr() ); + Feed fnew = feeds.getFeed(sub.getFeedId(), apiError); if ( fnew == null ) { logger.warn( "Specified feed " + sub.getFeedId() + " not known to Bus Controller"); - return resp.error(); + return responseBuilder.error(apiError); } DR_SubService dr_subService = new DR_SubService(); sub.setSubId(name); - DR_Sub nsub = dr_subService.updateDr_Sub(sub, resp.getErr() ); + DR_Sub nsub = dr_subService.updateDr_Sub(sub, apiError); if ( nsub != null && nsub.isStatusValid() ) { - return resp.success(nsub); + return responseBuilder.success(nsub); } - return resp.error(); + return responseBuilder.error(apiError); } @DELETE @@ -193,24 +196,22 @@ public class DR_SubResource extends BaseLoggingClass { @ApiResponse( code = 400, message = "Error", response = ApiError.class ) }) @Path("/{subId}") - public Response deleteDr_Sub( - @PathParam("subId") String id - ){ + public Response deleteDr_Sub(@PathParam("subId") String id){ - ApiService resp = new ApiService(); + ApiError apiError = new ApiError(); try { - resp.required( "subId", id, ""); + checker.required( "subId", id); } catch ( RequiredFieldException rfe ) { - logger.debug( resp.toString() ); - return resp.error(); + logger.debug( rfe.getApiError().toString() ); + return responseBuilder.error(rfe.getApiError()); } DR_SubService dr_subService = new DR_SubService(); - dr_subService.removeDr_Sub(id, resp.getErr() ); - if ( ! resp.getErr().is2xx() ) { - return resp.error(); + dr_subService.removeDr_Sub(id, apiError); + if (!apiError.is2xx() ) { + return responseBuilder.error(apiError); } - return resp.success(Status.NO_CONTENT.getStatusCode(), null ); + return responseBuilder.success(Status.NO_CONTENT.getStatusCode(), null ); } @GET @@ -222,22 +223,21 @@ public class DR_SubResource extends BaseLoggingClass { @ApiResponse( code = 400, message = "Error", response = ApiError.class ) }) @Path("/{subId}") - public Response get( - @PathParam("subId") String id - ) { - ApiService resp = new ApiService(); + public Response get(@PathParam("subId") String id) { + + ApiError apiError = new ApiError(); try { - resp.required( "subId", id, ""); + checker.required( "subId", id); } catch ( RequiredFieldException rfe ) { - logger.debug( resp.toString() ); - return resp.error(); + logger.debug( rfe.getApiError().toString() ); + return responseBuilder.error(rfe.getApiError()); } DR_SubService dr_subService = new DR_SubService(); - DR_Sub sub = dr_subService.getDr_Sub( id, resp.getErr() ); + DR_Sub sub = dr_subService.getDr_Sub(id, apiError); if ( sub != null && sub.isStatusValid() ) { - return resp.success(sub); + return responseBuilder.success(sub); } - return resp.error(); + return responseBuilder.error(apiError); } } diff --git a/src/main/java/org/onap/dmaap/dbcapi/resources/DcaeLocationResource.java b/src/main/java/org/onap/dmaap/dbcapi/resources/DcaeLocationResource.java index 8cb5336..89c9b49 100644 --- a/src/main/java/org/onap/dmaap/dbcapi/resources/DcaeLocationResource.java +++ b/src/main/java/org/onap/dmaap/dbcapi/resources/DcaeLocationResource.java @@ -41,13 +41,14 @@ import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.ws.rs.core.Response.Status; -import org.apache.log4j.Logger; import org.onap.dmaap.dbcapi.logging.BaseLoggingClass; import org.onap.dmaap.dbcapi.model.ApiError; import org.onap.dmaap.dbcapi.model.DcaeLocation; -import org.onap.dmaap.dbcapi.service.ApiService; import org.onap.dmaap.dbcapi.service.DcaeLocationService; +import static javax.ws.rs.core.Response.Status.NOT_FOUND; +import static javax.ws.rs.core.Response.Status.NO_CONTENT; + @Path("/dcaeLocations") @Api( value= "dcaeLocations", description = "an OpenStack tenant purposed for OpenDCAE (i.e. where OpenDCAE components might be deployed)" ) @@ -55,8 +56,8 @@ import org.onap.dmaap.dbcapi.service.DcaeLocationService; @Produces(MediaType.APPLICATION_JSON) @Authorization public class DcaeLocationResource extends BaseLoggingClass { - static final Logger logger = Logger.getLogger(DcaeLocationResource.class); - DcaeLocationService locationService = new DcaeLocationService(); + private DcaeLocationService locationService = new DcaeLocationService(); + private ResponseBuilder responseBuilder = new ResponseBuilder(); @GET @ApiOperation( value = "return dcaeLocation details", @@ -67,13 +68,10 @@ public class DcaeLocationResource extends BaseLoggingClass { @ApiResponse( code = 400, message = "Error", response = ApiError.class ) }) public Response getDcaeLocations() { - ApiService check = new ApiService(); - List<DcaeLocation> locs = locationService.getAllDcaeLocations(); - GenericEntity<List<DcaeLocation>> list = new GenericEntity<List<DcaeLocation>>(locs) { - }; - return check.success(list); + GenericEntity<List<DcaeLocation>> list = new GenericEntity<List<DcaeLocation>>(locs) {}; + return responseBuilder.success(list); } @POST @@ -84,22 +82,14 @@ public class DcaeLocationResource extends BaseLoggingClass { @ApiResponse( code = 200, message = "Success", response = DcaeLocation.class), @ApiResponse( code = 400, message = "Error", response = ApiError.class ) }) - public Response addDcaeLocation( - DcaeLocation location - ) { - ApiService check = new ApiService(); + public Response addDcaeLocation(DcaeLocation location) { if ( locationService.getDcaeLocation(location.getDcaeLocationName()) != null ) { - - check.setCode(Status.CONFLICT.getStatusCode()); - check.setMessage("dcaeLocation already exists"); - check.setFields("dcaeLocation"); - - return check.error(); - + return responseBuilder.error(new ApiError(Status.CONFLICT.getStatusCode(), + "dcaeLocation already exists", "dcaeLocation")); } DcaeLocation loc = locationService.addDcaeLocation(location); - return check.success(Status.CREATED.getStatusCode(), loc); + return responseBuilder.success(Status.CREATED.getStatusCode(), loc); } @PUT @@ -112,25 +102,15 @@ public class DcaeLocationResource extends BaseLoggingClass { }) @Path("/{locationName}") public Response updateDcaeLocation( - @PathParam("locationName") String name, - DcaeLocation location - ) { - ApiService check = new ApiService(); + @PathParam("locationName") String name, DcaeLocation location) { location.setDcaeLocationName(name); if ( locationService.getDcaeLocation(location.getDcaeLocationName()) == null ) { - ApiError err = new ApiError(); - - err.setCode(Status.NOT_FOUND.getStatusCode()); - err.setMessage("dcaeLocation does not exist"); - err.setFields("dcaeLocation"); - - return check.notFound(); - + return responseBuilder.notFound(); } DcaeLocation loc = locationService.updateDcaeLocation(location); - return check.success(Status.CREATED.getStatusCode(), loc ); + return responseBuilder.success(Status.CREATED.getStatusCode(), loc ); } @DELETE @@ -143,10 +123,8 @@ public class DcaeLocationResource extends BaseLoggingClass { public Response deleteDcaeLocation( @PathParam("locationName") String name ){ - ApiService check = new ApiService(); - locationService.removeDcaeLocation(name); - return check.success(Status.NO_CONTENT.getStatusCode(), null); + return responseBuilder.success(NO_CONTENT.getStatusCode(), null); } @GET @@ -157,23 +135,19 @@ public class DcaeLocationResource extends BaseLoggingClass { }) @Path("/{locationName}") public Response getDcaeLocation( - @PathParam("locationName") String name - ) { - ApiService check = new ApiService(); + @PathParam("locationName") String name) { DcaeLocation loc = locationService.getDcaeLocation( name ); if ( loc == null ) { ApiError err = new ApiError(); - err.setCode(Status.NOT_FOUND.getStatusCode()); + err.setCode(NOT_FOUND.getStatusCode()); err.setMessage("dcaeLocation does not exist"); err.setFields("dcaeLocation"); - return check.error(); - - + return responseBuilder.error(err); } - return check.success(loc); + return responseBuilder.success(loc); } } diff --git a/src/main/java/org/onap/dmaap/dbcapi/resources/DmaapResource.java b/src/main/java/org/onap/dmaap/dbcapi/resources/DmaapResource.java index bd30055..955cab7 100644 --- a/src/main/java/org/onap/dmaap/dbcapi/resources/DmaapResource.java +++ b/src/main/java/org/onap/dmaap/dbcapi/resources/DmaapResource.java @@ -7,9 +7,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -24,11 +24,14 @@ package org.onap.dmaap.dbcapi.resources; - import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiResponse; import io.swagger.annotations.ApiResponses; +import org.onap.dmaap.dbcapi.logging.BaseLoggingClass; +import org.onap.dmaap.dbcapi.model.ApiError; +import org.onap.dmaap.dbcapi.model.Dmaap; +import org.onap.dmaap.dbcapi.service.DmaapService; import javax.ws.rs.Consumes; import javax.ws.rs.GET; @@ -41,13 +44,6 @@ import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.ws.rs.core.UriInfo; -import org.onap.dmaap.dbcapi.logging.BaseLoggingClass; -import org.onap.dmaap.dbcapi.model.ApiError; -import org.onap.dmaap.dbcapi.model.Dmaap; -import org.onap.dmaap.dbcapi.service.ApiService; -import org.onap.dmaap.dbcapi.service.DmaapService; - - @Path("/dmaap") @Api( value= "dmaap", description = "Endpoint for this instance of DMaaP object containing values for this OpenDCAE deployment" ) @@ -57,8 +53,10 @@ import org.onap.dmaap.dbcapi.service.DmaapService; public class DmaapResource extends BaseLoggingClass { - DmaapService dmaapService = new DmaapService(); - + private DmaapService dmaapService = new DmaapService(); + private ResponseBuilder responseBuilder = new ResponseBuilder(); + private RequiredChecker checker = new RequiredChecker(); + @GET @ApiOperation( value = "return dmaap details", notes = "returns the `dmaap` object, which contains system wide configuration settings", response = Dmaap.class) @ApiResponses( value = { @@ -67,12 +65,10 @@ public class DmaapResource extends BaseLoggingClass { }) public Response getDmaap(@Context UriInfo uriInfo) { - ApiService check = new ApiService(); - Dmaap d = dmaapService.getDmaap(); - return check.success(d); + return responseBuilder.success(d); } - + @POST @ApiOperation( value = "return dmaap details", notes = "Create a new DMaaP set system wide configuration settings for the *dcaeEnvironment*. Deprecated with introduction of persistence in 1610.", response = Dmaap.class) @ApiResponses( value = { @@ -80,26 +76,22 @@ public class DmaapResource extends BaseLoggingClass { @ApiResponse( code = 400, message = "Error", response = ApiError.class ) }) public Response addDmaap( Dmaap obj ) { - ApiService check = new ApiService(); - try { //check for required fields - check.required( "dmaapName", obj.getDmaapName(), "^\\S+$" ); //no white space allowed in dmaapName - check.required( "dmaapProvUrl", obj.getDrProvUrl(), "" ); - check.required( "topicNsRoot", obj.getTopicNsRoot(), "" ); - check.required( "bridgeAdminTopic", obj.getBridgeAdminTopic(), "" ); + try { + validateRequiredFields(obj); } catch( RequiredFieldException rfe ) { - return check.error(); + return responseBuilder.error(rfe.getApiError()); } - + Dmaap d = dmaapService.addDmaap(obj); if ( d == null ) { - return check.notFound(); + return responseBuilder.notFound(); - } + } - return check.success(d); + return responseBuilder.success(d); } - + @PUT @ApiOperation( value = "return dmaap details", notes = "Update system settings for *dcaeEnvironment*.", response = Dmaap.class) @ApiResponses( value = { @@ -107,23 +99,25 @@ public class DmaapResource extends BaseLoggingClass { @ApiResponse( code = 400, message = "Error", response = ApiError.class ) }) public Response updateDmaap( Dmaap obj ) { - ApiService check = new ApiService(); - try { //check for required fields - check.required( "dmaapName", obj.getDmaapName(), "^\\S+$" ); //no white space allowed in dmaapName - check.required( "dmaapProvUrl", obj.getDrProvUrl(), "" ); - check.required( "topicNsRoot", obj.getTopicNsRoot(), "" ); - check.required( "bridgeAdminTopic", obj.getBridgeAdminTopic(), "" ); + try { + validateRequiredFields(obj); } catch( RequiredFieldException rfe ) { - return check.error(); + return responseBuilder.error(rfe.getApiError()); } + Dmaap d = dmaapService.updateDmaap(obj); if ( d != null ) { - return check.success(d); + return responseBuilder.success(d); } else { - return check.notFound(); - } + return responseBuilder.notFound(); + } + } + + private void validateRequiredFields(Dmaap obj) throws RequiredFieldException { + checker.required( "dmaapName", obj.getDmaapName(), "^\\S+$" ); //no white space allowed in dmaapName + checker.required( "dmaapProvUrl", obj.getDrProvUrl()); + checker.required( "topicNsRoot", obj.getTopicNsRoot()); + checker.required( "bridgeAdminTopic", obj.getBridgeAdminTopic()); } - - } diff --git a/src/main/java/org/onap/dmaap/dbcapi/resources/FeedResource.java b/src/main/java/org/onap/dmaap/dbcapi/resources/FeedResource.java index a7b4f73..6589c0d 100644 --- a/src/main/java/org/onap/dmaap/dbcapi/resources/FeedResource.java +++ b/src/main/java/org/onap/dmaap/dbcapi/resources/FeedResource.java @@ -46,7 +46,6 @@ import org.onap.dmaap.dbcapi.model.ApiError; import org.onap.dmaap.dbcapi.model.DR_Pub; import org.onap.dmaap.dbcapi.model.Feed; import org.onap.dmaap.dbcapi.model.DmaapObject.DmaapObject_Status; -import org.onap.dmaap.dbcapi.service.ApiService; import org.onap.dmaap.dbcapi.service.FeedService; @@ -56,7 +55,10 @@ import org.onap.dmaap.dbcapi.service.FeedService; @Produces(MediaType.APPLICATION_JSON) @Authorization public class FeedResource extends BaseLoggingClass { - + + private ResponseBuilder responseBuilder = new ResponseBuilder(); + private RequiredChecker checker = new RequiredChecker(); + @GET @ApiOperation( value = "return Feed details", notes = "Returns array of `Feed` objects.", @@ -68,16 +70,13 @@ public class FeedResource extends BaseLoggingClass { public Response getFeeds( @QueryParam("feedName") String feedName, @QueryParam("version") String version, - @QueryParam("match") String match - ) { - - ApiService resp = new ApiService(); + @QueryParam("match") String match) { FeedService feedService = new FeedService(); List<Feed> nfeeds = feedService.getAllFeeds( feedName, version, match ); GenericEntity<List<Feed>> list = new GenericEntity<List<Feed>>(nfeeds) { }; - return resp.success(list); + return responseBuilder.success(list); } @@ -92,49 +91,48 @@ public class FeedResource extends BaseLoggingClass { }) public Response addFeed( @WebParam(name = "feed") Feed feed, - @QueryParam("useExisting") String useExisting - ) { + @QueryParam("useExisting") String useExisting) { - ApiService resp = new ApiService(); + ApiError apiError = new ApiError(); try { - resp.required( "feedName", feed.getFeedName(), ""); - resp.required( "feedVersion", feed.getFeedVersion(), ""); - resp.required( "owner", feed.getOwner(), "" ); - resp.required( "asprClassification", feed.getAsprClassification(), "" ); + checker.required( "feedName", feed.getFeedName()); + checker.required( "feedVersion", feed.getFeedVersion()); + checker.required( "owner", feed.getOwner()); + checker.required( "asprClassification", feed.getAsprClassification()); } catch ( RequiredFieldException rfe ) { - logger.debug( resp.toString() ); - return resp.error(); + logger.debug( rfe.getApiError().toString() ); + return responseBuilder.error(rfe.getApiError()); } FeedService feedService = new FeedService(); - Feed nfeed = feedService.getFeedByName( feed.getFeedName(), feed.getFeedVersion(), resp.getErr() ); + Feed nfeed = feedService.getFeedByName( feed.getFeedName(), feed.getFeedVersion(), apiError); if ( nfeed == null ) { - nfeed = feedService.addFeed( feed, resp.getErr() ); + nfeed = feedService.addFeed(feed, apiError); if ( nfeed != null ) { - return resp.success(nfeed); + return responseBuilder.success(nfeed); } else { logger.error( "Unable to create: " + feed.getFeedName() + ":" + feed.getFeedVersion()); - return resp.error(); + return responseBuilder.error(apiError); } } else if ( nfeed.getStatus() == DmaapObject_Status.DELETED ) { feed.setFeedId( nfeed.getFeedId()); - nfeed = feedService.updateFeed(feed, resp.getErr()); + nfeed = feedService.updateFeed(feed, apiError); if ( nfeed != null ) { - return resp.success(nfeed); + return responseBuilder.success(nfeed); } else { logger.info( "Unable to update: " + feed.getFeedName() + ":" + feed.getFeedVersion()); - return resp.error(); + return responseBuilder.error(apiError); } } else if ( (useExisting != null) && ("true".compareToIgnoreCase( useExisting ) == 0)) { - return resp.success(nfeed); + return responseBuilder.success(nfeed); } - resp.setCode(Status.CONFLICT.getStatusCode()); - return resp.error(); + apiError.setCode(Status.CONFLICT.getStatusCode()); + return responseBuilder.error(apiError); } @PUT @@ -148,22 +146,21 @@ public class FeedResource extends BaseLoggingClass { @Path("/{id}") public Response updateFeed( @PathParam("id") String id, - @WebParam(name = "feed") Feed feed - ) { + @WebParam(name = "feed") Feed feed) { FeedService feedService = new FeedService(); - ApiService resp = new ApiService(); + ApiError apiError = new ApiError(); try { - resp.required( "feedId", id, ""); + checker.required( "feedId", id); } catch ( RequiredFieldException rfe ) { - logger.debug( resp.toString() ); - return resp.error(); + logger.debug( rfe.getApiError().toString() ); + return responseBuilder.error(rfe.getApiError()); } - Feed nfeed = feedService.getFeed( id, resp.getErr() ); + Feed nfeed = feedService.getFeed(id, apiError); if ( nfeed == null || nfeed.getStatus() == DmaapObject_Status.DELETED ) { - return resp.notFound(); + return responseBuilder.notFound(); } // we assume there is no updates allowed for pubs and subs objects via this api... @@ -172,13 +169,13 @@ public class FeedResource extends BaseLoggingClass { nfeed.setFeedDescription(feed.getFeedDescription()); nfeed.setFormatUuid(feed.getFormatUuid()); - nfeed = feedService.updateFeed(nfeed, resp.getErr()); + nfeed = feedService.updateFeed(nfeed, apiError); if ( nfeed != null ) { - return resp.success(nfeed); + return responseBuilder.success(nfeed); } else { logger.info( "Unable to update: " + feed.getFeedName() + ":" + feed.getFeedVersion()); - return resp.error(); + return responseBuilder.error(apiError); } } @@ -191,25 +188,23 @@ public class FeedResource extends BaseLoggingClass { @ApiResponse( code = 400, message = "Error", response = ApiError.class ) }) @Path("/{id}") - public Response deleteFeed( - @PathParam("id") String id - ){ - ApiService resp = new ApiService(); + public Response deleteFeed(@PathParam("id") String id){ + ApiError apiError = new ApiError(); logger.debug( "Entry: DELETE " + id); FeedService feedService = new FeedService(); - Feed nfeed = feedService.getFeed( id, resp.getErr() ); + Feed nfeed = feedService.getFeed(id, apiError); if ( nfeed == null ) { - resp.setCode(Status.NOT_FOUND.getStatusCode()); - return resp.error(); + apiError.setCode(Status.NOT_FOUND.getStatusCode()); + return responseBuilder.error(apiError); } - nfeed = feedService.removeFeed( nfeed, resp.getErr() ); + nfeed = feedService.removeFeed(nfeed, apiError); if ( nfeed == null || nfeed.getStatus() == DmaapObject_Status.DELETED ) { - return resp.success(Status.NO_CONTENT.getStatusCode(), null); + return responseBuilder.success(Status.NO_CONTENT.getStatusCode(), null); } logger.info( "Unable to delete: " + id + ":" + nfeed.getFeedVersion()); - return resp.error(); + return responseBuilder.error(apiError); } @GET @@ -221,17 +216,45 @@ public class FeedResource extends BaseLoggingClass { @ApiResponse( code = 400, message = "Error", response = ApiError.class ) }) @Path("/{id}") - public Response getFeed( - @PathParam("id") String id - ) { - ApiService resp = new ApiService(); + public Response getFeed(@PathParam("id") String id) { + ApiError apiError = new ApiError(); FeedService feedService = new FeedService(); - Feed nfeed = feedService.getFeed( id, resp.getErr() ); + Feed nfeed = feedService.getFeed(id, apiError); if ( nfeed == null ) { - resp.setCode(Status.NOT_FOUND.getStatusCode()); - return resp.error(); + apiError.setCode(Status.NOT_FOUND.getStatusCode()); + return responseBuilder.error(apiError); } - return resp.success(nfeed); + return responseBuilder.success(nfeed); } + + @PUT + @ApiOperation( value = "sync feeds to existing DR", + notes = "When Bus Controller is deployed after DR, then it is possible" + + "that DR has previous provisioning data that needs to be imported" + + "into Bus Controller.", + response = Feed.class ) + @ApiResponses( value = { + @ApiResponse( code = 200, message = "Success", response = Feed.class), + @ApiResponse( code = 400, message = "Error", response = ApiError.class ) + }) + @Path( "/sync") + public Response syncFeeds (@QueryParam("hard") String hardParam) { + ApiError error = new ApiError(); + + FeedService feedService = new FeedService(); + boolean hard = false; + if ( hardParam != null && hardParam.equalsIgnoreCase("true")) { + hard = true; + } + feedService.sync( hard, error ); + if ( error.is2xx()) { + List<Feed> nfeeds = feedService.getAllFeeds(); + GenericEntity<List<Feed>> list = new GenericEntity<List<Feed>>(nfeeds) { + }; + return responseBuilder.success(list); + } + return responseBuilder.error(error); + } + } diff --git a/src/main/java/org/onap/dmaap/dbcapi/resources/InfoResource.java b/src/main/java/org/onap/dmaap/dbcapi/resources/InfoResource.java index 31c22ba..bcb7ed2 100644 --- a/src/main/java/org/onap/dmaap/dbcapi/resources/InfoResource.java +++ b/src/main/java/org/onap/dmaap/dbcapi/resources/InfoResource.java @@ -32,8 +32,6 @@ import io.swagger.annotations.ApiResponses; import javax.ws.rs.Consumes; import javax.ws.rs.GET; -import javax.ws.rs.POST; -import javax.ws.rs.PUT; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.core.Context; @@ -44,8 +42,6 @@ import javax.ws.rs.core.UriInfo; import org.onap.dmaap.dbcapi.logging.BaseLoggingClass; import org.onap.dmaap.dbcapi.model.ApiError; import org.onap.dmaap.dbcapi.model.Dmaap; -import org.onap.dmaap.dbcapi.service.ApiService; -import org.onap.dmaap.dbcapi.service.DmaapService; @@ -57,7 +53,7 @@ import org.onap.dmaap.dbcapi.service.DmaapService; public class InfoResource extends BaseLoggingClass { - DmaapService dmaapService = new DmaapService(); + private ResponseBuilder responseBuilder = new ResponseBuilder(); @GET @ApiOperation( value = "return info details", notes = "returns the `info` object", response = Dmaap.class) @@ -67,9 +63,7 @@ public class InfoResource extends BaseLoggingClass { }) public Response getInfo(@Context UriInfo uriInfo) { - ApiService check = new ApiService(); - - return check.success(204, null); + return responseBuilder.success(204, null); } diff --git a/src/main/java/org/onap/dmaap/dbcapi/resources/MR_ClientResource.java b/src/main/java/org/onap/dmaap/dbcapi/resources/MR_ClientResource.java index a621338..6df8ef6 100644 --- a/src/main/java/org/onap/dmaap/dbcapi/resources/MR_ClientResource.java +++ b/src/main/java/org/onap/dmaap/dbcapi/resources/MR_ClientResource.java @@ -45,11 +45,12 @@ import org.onap.dmaap.dbcapi.model.ApiError; import org.onap.dmaap.dbcapi.model.MR_Client; import org.onap.dmaap.dbcapi.model.MR_Cluster; import org.onap.dmaap.dbcapi.model.Topic; -import org.onap.dmaap.dbcapi.service.ApiService; import org.onap.dmaap.dbcapi.service.MR_ClientService; import org.onap.dmaap.dbcapi.service.MR_ClusterService; import org.onap.dmaap.dbcapi.service.TopicService; +import static javax.ws.rs.core.Response.Status.NO_CONTENT; + @Path("/mr_clients") @Api( value= "MR_Clients", description = "Endpoint for a Message Router Client that implements a Publisher or a Subscriber" ) @@ -59,6 +60,8 @@ import org.onap.dmaap.dbcapi.service.TopicService; public class MR_ClientResource extends BaseLoggingClass { private MR_ClientService mr_clientService = new MR_ClientService(); + private ResponseBuilder responseBuilder = new ResponseBuilder(); + private RequiredChecker checker = new RequiredChecker(); @GET @ApiOperation( value = "return MR_Client details", @@ -69,13 +72,11 @@ public class MR_ClientResource extends BaseLoggingClass { @ApiResponse( code = 400, message = "Error", response = ApiError.class ) }) public Response getMr_Clients() { - ApiService resp = new ApiService(); - List<MR_Client> clients = mr_clientService.getAllMr_Clients(); GenericEntity<List<MR_Client>> list = new GenericEntity<List<MR_Client>>(clients) { }; - return resp.success(list); + return responseBuilder.success(list); } @POST @@ -89,59 +90,57 @@ public class MR_ClientResource extends BaseLoggingClass { @ApiResponse( code = 200, message = "Success", response = MR_Client.class), @ApiResponse( code = 400, message = "Error", response = ApiError.class ) }) - public Response addMr_Client( - MR_Client client - ) { - ApiService resp = new ApiService(); + public Response addMr_Client(MR_Client client) { + ApiError apiError = new ApiError(); try { - resp.required( "fqtn", client.getFqtn(), ""); - resp.required( "dcaeLocationName", client.getDcaeLocationName(), ""); + checker.required( "fqtn", client.getFqtn()); + checker.required( "dcaeLocationName", client.getDcaeLocationName()); String s = client.getClientRole(); if ( s == null ) { s = client.getClientIdentity(); } - resp.required( "clientRole or clientIdentity", s, "" ); - resp.required( "action", client.getAction(), ""); + checker.required( "clientRole or clientIdentity", s); + checker.required( "action", client.getAction()); } catch ( RequiredFieldException rfe ) { - logger.debug( resp.toString() ); - return resp.error(); + logger.debug( rfe.getApiError().toString() ); + return responseBuilder.error(rfe.getApiError()); } MR_ClusterService clusters = new MR_ClusterService(); - MR_Cluster cluster = clusters.getMr_Cluster(client.getDcaeLocationName(), resp.getErr()); + MR_Cluster cluster = clusters.getMr_Cluster(client.getDcaeLocationName(), apiError); if ( cluster == null ) { - resp.setCode(Status.BAD_REQUEST.getStatusCode()); - resp.setMessage( "MR_Cluster alias not found for dcaeLocation: " + client.getDcaeLocationName()); - resp.setFields("dcaeLocationName"); - logger.warn( resp.toString() ); - return resp.error(); + apiError.setCode(Status.BAD_REQUEST.getStatusCode()); + apiError.setMessage( "MR_Cluster alias not found for dcaeLocation: " + client.getDcaeLocationName()); + apiError.setFields("dcaeLocationName"); + logger.warn(apiError.toString()); + return responseBuilder.error(apiError); } String url = cluster.getFqdn(); if ( url == null || url.isEmpty() ) { - resp.setCode(Status.BAD_REQUEST.getStatusCode()); - resp.setMessage("FQDN not set for dcaeLocation " + client.getDcaeLocationName() ); - resp.setFields("fqdn"); - logger.warn( resp.toString() ); - return resp.error(); + apiError.setCode(Status.BAD_REQUEST.getStatusCode()); + apiError.setMessage("FQDN not set for dcaeLocation " + client.getDcaeLocationName() ); + apiError.setFields("fqdn"); + logger.warn(apiError.toString()); + return responseBuilder.error(apiError); } TopicService topics = new TopicService(); - Topic t = topics.getTopic(client.getFqtn(), resp.getErr() ); + Topic t = topics.getTopic(client.getFqtn(), apiError); if ( t == null ) { - return resp.error(); + return responseBuilder.error(apiError); } - MR_Client nClient = mr_clientService.addMr_Client(client, t, resp.getErr()); - if ( resp.getErr().is2xx()) { - t = topics.getTopic(client.getFqtn(), resp.getErr()); - topics.checkForBridge(t, resp.getErr()); - return resp.success(nClient); + MR_Client nClient = mr_clientService.addMr_Client(client, t, apiError); + if (apiError.is2xx()) { + t = topics.getTopic(client.getFqtn(), apiError); + topics.checkForBridge(t, apiError); + return responseBuilder.success(nClient); } else { - return resp.error(); + return responseBuilder.error(apiError); } } @@ -154,30 +153,27 @@ public class MR_ClientResource extends BaseLoggingClass { @ApiResponse( code = 400, message = "Error", response = ApiError.class ) }) @Path("/{clientId}") - public Response updateMr_Client( - @PathParam("clientId") String clientId, - MR_Client client - ) { - ApiService resp = new ApiService(); + public Response updateMr_Client(@PathParam("clientId") String clientId, MR_Client client) { + ApiError apiError = new ApiError(); try { - resp.required( "fqtn", client.getFqtn(), ""); - resp.required( "dcaeLocationName", client.getDcaeLocationName(), ""); - resp.required( "clientRole", client.getClientRole(), "" ); - resp.required( "action", client.getAction(), ""); + checker.required( "fqtn", client.getFqtn()); + checker.required( "dcaeLocationName", client.getDcaeLocationName()); + checker.required( "clientRole", client.getClientRole()); + checker.required( "action", client.getAction()); } catch ( RequiredFieldException rfe ) { - logger.debug( resp.toString() ); - return resp.error(); + logger.debug( rfe.getApiError().toString() ); + return responseBuilder.error(rfe.getApiError()); } client.setMrClientId(clientId); - MR_Client nClient = mr_clientService.updateMr_Client(client, resp.getErr() ); - if ( resp.getErr().is2xx()) { + MR_Client nClient = mr_clientService.updateMr_Client(client, apiError); + if (apiError.is2xx()) { return Response.ok(nClient) .build(); } - return Response.status(resp.getErr().getCode()) - .entity( resp.getErr() ) + return Response.status(apiError.getCode()) + .entity(apiError) .build(); } @@ -190,23 +186,21 @@ public class MR_ClientResource extends BaseLoggingClass { @ApiResponse( code = 400, message = "Error", response = ApiError.class ) }) @Path("/{subId}") - public Response deleteMr_Client( - @PathParam("subId") String id - ){ - ApiService resp = new ApiService(); + public Response deleteMr_Client(@PathParam("subId") String id){ + ApiError apiError = new ApiError(); try { - resp.required( "clientId", id, ""); + checker.required( "clientId", id); } catch ( RequiredFieldException rfe ) { - logger.debug( resp.toString() ); - return resp.error(); + logger.debug( rfe.getApiError().toString() ); + return responseBuilder.error(rfe.getApiError()); } - mr_clientService.removeMr_Client(id, true, resp.getErr() ); - if ( resp.getErr().is2xx()) { - return resp.success(Status.NO_CONTENT.getStatusCode(), null); + mr_clientService.removeMr_Client(id, true, apiError); + if (apiError.is2xx()) { + return responseBuilder.success(NO_CONTENT.getStatusCode(), null); } - return resp.error(); + return responseBuilder.error(apiError); } @GET @@ -218,21 +212,19 @@ public class MR_ClientResource extends BaseLoggingClass { @ApiResponse( code = 400, message = "Error", response = ApiError.class ) }) @Path("/{subId}") - public Response test( - @PathParam("subId") String id - ) { - ApiService resp = new ApiService(); + public Response test(@PathParam("subId") String id) { + ApiError apiError = new ApiError(); try { - resp.required( "clientId", id, ""); + checker.required( "clientId", id); } catch ( RequiredFieldException rfe ) { - logger.debug( resp.toString() ); - return resp.error(); + logger.debug( rfe.getApiError().toString() ); + return responseBuilder.error(rfe.getApiError()); } - MR_Client nClient = mr_clientService.getMr_Client( id, resp.getErr() ); - if ( resp.getErr().is2xx()) { - return resp.success(nClient); + MR_Client nClient = mr_clientService.getMr_Client(id, apiError); + if (apiError.is2xx()) { + return responseBuilder.success(nClient); } - return resp.error(); + return responseBuilder.error(apiError); } } diff --git a/src/main/java/org/onap/dmaap/dbcapi/resources/MR_ClusterResource.java b/src/main/java/org/onap/dmaap/dbcapi/resources/MR_ClusterResource.java index 50ab4db..0a361ff 100644 --- a/src/main/java/org/onap/dmaap/dbcapi/resources/MR_ClusterResource.java +++ b/src/main/java/org/onap/dmaap/dbcapi/resources/MR_ClusterResource.java @@ -43,8 +43,6 @@ import javax.ws.rs.core.Response.Status; import org.onap.dmaap.dbcapi.logging.BaseLoggingClass; import org.onap.dmaap.dbcapi.model.ApiError; import org.onap.dmaap.dbcapi.model.MR_Cluster; -import org.onap.dmaap.dbcapi.service.ApiService; -import org.onap.dmaap.dbcapi.service.MR_ClientService; import org.onap.dmaap.dbcapi.service.MR_ClusterService; @@ -55,8 +53,9 @@ import org.onap.dmaap.dbcapi.service.MR_ClusterService; @Authorization public class MR_ClusterResource extends BaseLoggingClass { - MR_ClusterService mr_clusterService = new MR_ClusterService(); - MR_ClientService mr_clients = new MR_ClientService(); + private MR_ClusterService mr_clusterService = new MR_ClusterService(); + private ResponseBuilder responseBuilder = new ResponseBuilder(); + private RequiredChecker checker = new RequiredChecker(); @GET @ApiOperation( value = "return MR_Cluster details", @@ -67,13 +66,11 @@ public class MR_ClusterResource extends BaseLoggingClass { @ApiResponse( code = 400, message = "Error", response = ApiError.class ) }) public Response getMr_Clusters() { - ApiService resp = new ApiService(); - List<MR_Cluster> clusters = mr_clusterService.getAllMr_Clusters(); GenericEntity<List<MR_Cluster>> list = new GenericEntity<List<MR_Cluster>>(clusters) { }; - return resp.success(list); + return responseBuilder.success(list); } @POST @@ -84,22 +81,20 @@ public class MR_ClusterResource extends BaseLoggingClass { @ApiResponse( code = 200, message = "Success", response = MR_Cluster.class), @ApiResponse( code = 400, message = "Error", response = ApiError.class ) }) - public Response addMr_Cluster( - MR_Cluster cluster - ) { - ApiService resp = new ApiService(); + public Response addMr_Cluster(MR_Cluster cluster) { + ApiError apiError = new ApiError(); try { - resp.required( "dcaeLocationName", cluster.getDcaeLocationName(), "" ); - resp.required( "fqdn", cluster.getFqdn(), "" ); + checker.required( "dcaeLocationName", cluster.getDcaeLocationName()); + checker.required( "fqdn", cluster.getFqdn()); } catch( RequiredFieldException rfe ) { - return resp.error(); + return responseBuilder.error(rfe.getApiError()); } - MR_Cluster mrc = mr_clusterService.addMr_Cluster(cluster, resp.getErr() ); + MR_Cluster mrc = mr_clusterService.addMr_Cluster(cluster, apiError); if ( mrc != null && mrc.isStatusValid() ) { - return resp.success(Status.CREATED.getStatusCode(), mrc); + return responseBuilder.success(Status.CREATED.getStatusCode(), mrc); } - return resp.error(); + return responseBuilder.error(apiError); } @@ -112,24 +107,21 @@ public class MR_ClusterResource extends BaseLoggingClass { @ApiResponse( code = 400, message = "Error", response = ApiError.class ) }) @Path("/{clusterId}") - public Response updateMr_Cluster( - @PathParam("clusterId") String clusterId, - MR_Cluster cluster - ) { - ApiService resp = new ApiService(); + public Response updateMr_Cluster(@PathParam("clusterId") String clusterId, MR_Cluster cluster) { + ApiError apiError = new ApiError(); try { - resp.required( "fqdn", clusterId, "" ); - resp.required( "dcaeLocationName", cluster.getDcaeLocationName(), "" ); + checker.required( "fqdn", clusterId); + checker.required( "dcaeLocationName", cluster.getDcaeLocationName()); } catch( RequiredFieldException rfe ) { - return resp.error(); + return responseBuilder.error(rfe.getApiError()); } cluster.setDcaeLocationName(clusterId); - MR_Cluster mrc = mr_clusterService.updateMr_Cluster(cluster, resp.getErr() ); + MR_Cluster mrc = mr_clusterService.updateMr_Cluster(cluster, apiError); if ( mrc != null && mrc.isStatusValid() ) { - return resp.success(Status.CREATED.getStatusCode(), mrc); + return responseBuilder.success(Status.CREATED.getStatusCode(), mrc); } - return resp.error(); + return responseBuilder.error(apiError); } @DELETE @@ -141,21 +133,19 @@ public class MR_ClusterResource extends BaseLoggingClass { @ApiResponse( code = 400, message = "Error", response = ApiError.class ) }) @Path("/{clusterId}") - public Response deleteMr_Cluster( - @PathParam("clusterId") String id - ){ - ApiService resp = new ApiService(); + public Response deleteMr_Cluster(@PathParam("clusterId") String id){ + ApiError apiError = new ApiError(); try { - resp.required( "fqdn", id, "" ); + checker.required( "fqdn", id); } catch( RequiredFieldException rfe ) { - return resp.error(); + return responseBuilder.error(rfe.getApiError()); } - mr_clusterService.removeMr_Cluster(id, resp.getErr() ); - if ( resp.getErr().is2xx()) { - return resp.success(Status.NO_CONTENT.getStatusCode(), null); + mr_clusterService.removeMr_Cluster(id, apiError); + if (apiError.is2xx()) { + return responseBuilder.success(Status.NO_CONTENT.getStatusCode(), null); } - return resp.error(); + return responseBuilder.error(apiError); } @GET @@ -167,20 +157,18 @@ public class MR_ClusterResource extends BaseLoggingClass { @ApiResponse( code = 400, message = "Error", response = ApiError.class ) }) @Path("/{clusterId}") - public Response getMR_Cluster( - @PathParam("clusterId") String id - ) { - ApiService resp = new ApiService(); + public Response getMR_Cluster(@PathParam("clusterId") String id) { + ApiError apiError = new ApiError(); try { - resp.required( "dcaeLocationName", id, "" ); + checker.required( "dcaeLocationName", id); } catch( RequiredFieldException rfe ) { - return resp.error(); + return responseBuilder.error(rfe.getApiError()); } - MR_Cluster mrc = mr_clusterService.getMr_Cluster( id, resp.getErr() ); + MR_Cluster mrc = mr_clusterService.getMr_Cluster(id, apiError); if ( mrc != null && mrc.isStatusValid() ) { - return resp.success(Status.CREATED.getStatusCode(), mrc); + return responseBuilder.success(Status.CREATED.getStatusCode(), mrc); } - return resp.error(); + return responseBuilder.error(apiError); } } diff --git a/src/main/java/org/onap/dmaap/dbcapi/resources/RequestTimeLogFilter.java b/src/main/java/org/onap/dmaap/dbcapi/resources/RequestTimeLogFilter.java new file mode 100644 index 0000000..b2b98b6 --- /dev/null +++ b/src/main/java/org/onap/dmaap/dbcapi/resources/RequestTimeLogFilter.java @@ -0,0 +1,55 @@ +/*-
+ * ============LICENSE_START=======================================================
+ * org.onap.dmaap
+ * ================================================================================
+ * Copyright (C) 2019 Nokia Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.dmaap.dbcapi.resources;
+
+import com.att.eelf.configuration.EELFLogger;
+import java.time.Clock;
+import javax.ws.rs.container.ContainerRequestContext;
+import javax.ws.rs.container.ContainerRequestFilter;
+import javax.ws.rs.container.ContainerResponseContext;
+import javax.ws.rs.container.ContainerResponseFilter;
+import org.onap.dmaap.dbcapi.logging.BaseLoggingClass;
+
+public class RequestTimeLogFilter extends BaseLoggingClass implements ContainerRequestFilter, ContainerResponseFilter {
+
+ private final EELFLogger log;
+ private Clock clock;
+
+ public RequestTimeLogFilter() {
+ this(auditLogger, Clock.systemDefaultZone());
+ }
+
+ RequestTimeLogFilter(EELFLogger logger, Clock clock) {
+ this.log = logger;
+ this.clock = clock;
+ }
+
+ @Override
+ public void filter(ContainerRequestContext requestContext) {
+ requestContext.setProperty("start", clock.millis());
+ }
+
+ @Override
+ public void filter(ContainerRequestContext requestContext, ContainerResponseContext containerResponseContext) {
+ long startTime = (long) requestContext.getProperty("start");
+ long elapsedTime = clock.millis() - startTime;
+ log.info("Request took {} ms", elapsedTime);
+ }
+}
diff --git a/src/main/java/org/onap/dmaap/dbcapi/resources/RequiredChecker.java b/src/main/java/org/onap/dmaap/dbcapi/resources/RequiredChecker.java new file mode 100644 index 0000000..36f0215 --- /dev/null +++ b/src/main/java/org/onap/dmaap/dbcapi/resources/RequiredChecker.java @@ -0,0 +1,53 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2019 NOKIA Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.dmaap.dbcapi.resources; + +import org.onap.dmaap.dbcapi.model.ApiError; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import static javax.ws.rs.core.Response.Status.BAD_REQUEST; + +public class RequiredChecker { + + public void required(String name, Object val) throws RequiredFieldException { + if (val == null) { + throw new RequiredFieldException(new ApiError(BAD_REQUEST.getStatusCode(), + "missing required field", name)); + } + } + + public void required(String name, String val, String expr) throws RequiredFieldException { + + required(name, val); + + if (expr != null && !expr.isEmpty()) { + Pattern pattern = Pattern.compile(expr); + Matcher matcher = pattern.matcher(val); + if (!matcher.find()) { + throw new RequiredFieldException(new ApiError(BAD_REQUEST.getStatusCode(), + "value '" + val + "' violates regexp check '" + expr + "'", name)); + } + } + } + +} diff --git a/src/main/java/org/onap/dmaap/dbcapi/resources/RequiredFieldException.java b/src/main/java/org/onap/dmaap/dbcapi/resources/RequiredFieldException.java index 74af356..2968d18 100644 --- a/src/main/java/org/onap/dmaap/dbcapi/resources/RequiredFieldException.java +++ b/src/main/java/org/onap/dmaap/dbcapi/resources/RequiredFieldException.java @@ -7,9 +7,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -20,11 +20,27 @@ package org.onap.dmaap.dbcapi.resources; +import org.onap.dmaap.dbcapi.model.ApiError; + public class RequiredFieldException extends Exception { - /** - * - */ - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 2L; + + private final ApiError apiError; + + public RequiredFieldException(ApiError apiError) { + super(); + this.apiError = apiError; + } + + public ApiError getApiError() { + return apiError; + } + @Override + public String toString() { + return "RequiredFieldException{" + + "apiError=" + apiError + + '}'; + } } diff --git a/src/main/java/org/onap/dmaap/dbcapi/resources/ResponseBuilder.java b/src/main/java/org/onap/dmaap/dbcapi/resources/ResponseBuilder.java new file mode 100644 index 0000000..5d78aaf --- /dev/null +++ b/src/main/java/org/onap/dmaap/dbcapi/resources/ResponseBuilder.java @@ -0,0 +1,85 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2019 NOKIA Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + + +package org.onap.dmaap.dbcapi.resources; + +import org.onap.dmaap.dbcapi.logging.BaseLoggingClass; +import org.onap.dmaap.dbcapi.model.ApiError; +import org.slf4j.MDC; + +import javax.ws.rs.core.Response; + +import static com.att.eelf.configuration.Configuration.MDC_RESPONSE_CODE; +import static com.att.eelf.configuration.Configuration.MDC_RESPONSE_DESC; +import static com.att.eelf.configuration.Configuration.MDC_STATUS_CODE; +import static javax.ws.rs.core.Response.Status.NOT_FOUND; +import static javax.ws.rs.core.Response.Status.SERVICE_UNAVAILABLE; +import static javax.ws.rs.core.Response.Status.UNAUTHORIZED; + +public class ResponseBuilder extends BaseLoggingClass { + + Response success(Object d) { + return buildSuccessResponse(d, Response.Status.OK.getStatusCode()); + } + + Response success(int code, Object d) { + return buildSuccessResponse(d, code); + } + + Response error(ApiError err) { + return buildErrResponse(err); + } + + Response unauthorized(String msg) { + return buildErrResponse(new ApiError(UNAUTHORIZED.getStatusCode(), msg, "Authorization")); + } + + Response unavailable() { + return buildErrResponse(new ApiError(SERVICE_UNAVAILABLE.getStatusCode(), + "Request is unavailable due to unexpected condition")); + } + + Response notFound() { + return buildErrResponse(new ApiError(NOT_FOUND.getStatusCode(),"Requested object not found")); + } + + private Response buildSuccessResponse(Object d, int code) { + MDC.put(MDC_STATUS_CODE, "COMPLETE"); + MDC.put(MDC_RESPONSE_DESC, ""); + return buildResponse(d, code); + } + + private Response buildErrResponse(ApiError err) { + MDC.put(MDC_STATUS_CODE, "ERROR"); + MDC.put(MDC_RESPONSE_DESC, err.getMessage()); + + return buildResponse(err, err.getCode()); + } + + private Response buildResponse(Object obj, int code) { + MDC.put(MDC_RESPONSE_CODE, String.valueOf(code)); + + auditLogger.auditEvent(""); + return Response.status(code) + .entity(obj) + .build(); + } +} diff --git a/src/main/java/org/onap/dmaap/dbcapi/resources/TopicResource.java b/src/main/java/org/onap/dmaap/dbcapi/resources/TopicResource.java index be1b3ac..3206cf7 100644 --- a/src/main/java/org/onap/dmaap/dbcapi/resources/TopicResource.java +++ b/src/main/java/org/onap/dmaap/dbcapi/resources/TopicResource.java @@ -46,10 +46,11 @@ import org.onap.dmaap.dbcapi.model.ApiError; import org.onap.dmaap.dbcapi.model.ReplicationType; import org.onap.dmaap.dbcapi.model.FqtnType; import org.onap.dmaap.dbcapi.model.Topic; -import org.onap.dmaap.dbcapi.service.ApiService; import org.onap.dmaap.dbcapi.service.TopicService; import org.onap.dmaap.dbcapi.util.DmaapConfig; +import static javax.ws.rs.core.Response.Status.CREATED; + @Path("/topics") @Api( value= "topics", description = "Endpoint for retreiving MR Topics" ) @Consumes(MediaType.APPLICATION_JSON) @@ -59,7 +60,9 @@ public class TopicResource extends BaseLoggingClass { private static FqtnType defaultTopicStyle; private static String defaultPartitionCount; private static String defaultReplicationCount; - TopicService mr_topicService = new TopicService(); + private TopicService mr_topicService = new TopicService(); + private ResponseBuilder responseBuilder = new ResponseBuilder(); + private RequiredChecker checker = new RequiredChecker(); public TopicResource() { DmaapConfig p = (DmaapConfig)DmaapConfig.getConfig(); @@ -79,14 +82,11 @@ public class TopicResource extends BaseLoggingClass { @ApiResponse( code = 400, message = "Error", response = ApiError.class ) }) public Response getTopics() { - - ApiService check = new ApiService(); - List<Topic> allTopics = mr_topicService.getAllTopics(); GenericEntity<List<Topic>> list = new GenericEntity<List<Topic>>(allTopics) { }; - return check.success(list); + return responseBuilder.success(list); } @@ -101,20 +101,17 @@ public class TopicResource extends BaseLoggingClass { @ApiResponse( code = 200, message = "Success", response = Topic.class), @ApiResponse( code = 400, message = "Error", response = ApiError.class ) }) - public Response addTopic( - Topic topic, - @QueryParam("useExisting") String useExisting - ) { + public Response addTopic(Topic topic, @QueryParam("useExisting") String useExisting) { logger.info( "addTopic request: " + topic + " useExisting=" + useExisting ); - ApiService check = new ApiService(); + ApiError apiError = new ApiError(); try { - check.required( "topicName", topic.getTopicName(), "^\\S+$" ); //no white space allowed in topicName - check.required( "topicDescription", topic.getTopicDescription(), "" ); - check.required( "owner", topic.getOwner(), "" ); + checker.required( "topicName", topic.getTopicName(), "^\\S+$" ); //no white space allowed in topicName + checker.required( "topicDescription", topic.getTopicDescription()); + checker.required( "owner", topic.getOwner()); } catch( RequiredFieldException rfe ) { - logger.error("Error", rfe); - return check.error(); + logger.error("Error", rfe.getApiError()); + return responseBuilder.error(rfe.getApiError()); } ReplicationType t = topic.getReplicationCase(); @@ -140,11 +137,11 @@ public class TopicResource extends BaseLoggingClass { flag = "true".compareToIgnoreCase( useExisting ) == 0; } - Topic mrc = mr_topicService.addTopic(topic, check.getErr(), flag); - if ( mrc != null && check.getErr().is2xx() ) { - return check.success(Status.CREATED.getStatusCode(), mrc); + Topic mrc = mr_topicService.addTopic(topic, apiError, flag); + if ( mrc != null && apiError.is2xx() ) { + return responseBuilder.success(CREATED.getStatusCode(), mrc); } - return check.error(); + return responseBuilder.error(apiError); } @PUT @@ -156,15 +153,13 @@ public class TopicResource extends BaseLoggingClass { @ApiResponse( code = 400, message = "Error", response = ApiError.class ) }) @Path("/{topicId}") - public Response updateTopic( - @PathParam("topicId") String topicId - ) { - ApiService check = new ApiService(); + public Response updateTopic(@PathParam("topicId") String topicId) { + ApiError apiError = new ApiError(); - check.setCode(Status.BAD_REQUEST.getStatusCode()); - check.setMessage( "Method /PUT not supported for /topics"); + apiError.setCode(Status.BAD_REQUEST.getStatusCode()); + apiError.setMessage( "Method /PUT not supported for /topics"); - return check.error(); + return responseBuilder.error(apiError); } @DELETE @@ -176,23 +171,21 @@ public class TopicResource extends BaseLoggingClass { @ApiResponse( code = 400, message = "Error", response = ApiError.class ) }) @Path("/{topicId}") - public Response deleteTopic( - @PathParam("topicId") String id - ){ - ApiService check = new ApiService(); + public Response deleteTopic(@PathParam("topicId") String id){ + ApiError apiError = new ApiError(); try { - check.required( "fqtn", id, "" ); + checker.required( "fqtn", id); } catch( RequiredFieldException rfe ) { - logger.error("Error", rfe); - return check.error(); + logger.error("Error", rfe.getApiError()); + return responseBuilder.error(rfe.getApiError()); } - mr_topicService.removeTopic(id, check.getErr()); - if ( check.getErr().is2xx()) { - return check.success(Status.NO_CONTENT.getStatusCode(), null); + mr_topicService.removeTopic(id, apiError); + if (apiError.is2xx()) { + return responseBuilder.success(Status.NO_CONTENT.getStatusCode(), null); } - return check.error(); + return responseBuilder.error(apiError); } @@ -205,22 +198,20 @@ public class TopicResource extends BaseLoggingClass { @ApiResponse( code = 400, message = "Error", response = ApiError.class ) }) @Path("/{topicId}") - public Response getTopic( - @PathParam("topicId") String id - ) { + public Response getTopic(@PathParam("topicId") String id) { logger.info("Entry: /GET " + id); - ApiService check = new ApiService(); + ApiError apiError = new ApiError(); try { - check.required( "topicName", id, "^\\S+$" ); //no white space allowed in topicName + checker.required( "topicName", id, "^\\S+$" ); //no white space allowed in topicName } catch( RequiredFieldException rfe ) { - logger.error("Error", rfe); - return check.error(); + logger.error("Error", rfe.getApiError()); + return responseBuilder.error(rfe.getApiError()); } - Topic mrc = mr_topicService.getTopic( id, check.getErr() ); + Topic mrc = mr_topicService.getTopic(id, apiError); if ( mrc == null ) { - return check.error(); + return responseBuilder.error(apiError); } - return check.success(mrc); + return responseBuilder.success(mrc); } } diff --git a/src/main/java/org/onap/dmaap/dbcapi/server/ApplicationConfig.java b/src/main/java/org/onap/dmaap/dbcapi/server/ApplicationConfig.java index 2283ea2..2244b73 100644 --- a/src/main/java/org/onap/dmaap/dbcapi/server/ApplicationConfig.java +++ b/src/main/java/org/onap/dmaap/dbcapi/server/ApplicationConfig.java @@ -20,8 +20,8 @@ package org.onap.dmaap.dbcapi.server; import org.glassfish.jersey.server.ResourceConfig; - - +import org.onap.dmaap.dbcapi.resources.RequestTimeLogFilter; +import org.onap.dmaap.dbcapi.resources.AuthorizationFilter; public class ApplicationConfig extends ResourceConfig { @@ -30,7 +30,8 @@ public class ApplicationConfig extends ResourceConfig { */ public ApplicationConfig() { - register(org.onap.dmaap.dbcapi.resources.AuthorizationFilter.class); + register(AuthorizationFilter.class). + register(RequestTimeLogFilter.class); } } diff --git a/src/main/java/org/onap/dmaap/dbcapi/server/JettyServer.java b/src/main/java/org/onap/dmaap/dbcapi/server/JettyServer.java index 81c08b2..7457ce9 100644 --- a/src/main/java/org/onap/dmaap/dbcapi/server/JettyServer.java +++ b/src/main/java/org/onap/dmaap/dbcapi/server/JettyServer.java @@ -22,7 +22,8 @@ package org.onap.dmaap.dbcapi.server; - +import com.google.common.collect.Sets; +import javax.servlet.DispatcherType; import org.eclipse.jetty.server.*; import org.eclipse.jetty.servlet.DefaultServlet; import org.eclipse.jetty.servlet.ServletContextHandler; @@ -31,6 +32,7 @@ import org.eclipse.jetty.util.ssl.SslContextFactory; import org.onap.dmaap.dbcapi.logging.BaseLoggingClass; import java.util.Properties; + /** * A Jetty server which supports: * - http and https (simultaneously for dev env) @@ -38,59 +40,47 @@ import java.util.Properties; * - static html pages (for documentation). */ public class JettyServer extends BaseLoggingClass { - private Server server; - - public Server getServer() { - return server; - } + private Server server; - public JettyServer( Properties params ) throws Exception { - - server = new Server(); - int httpPort = Integer.valueOf(params.getProperty("IntHttpPort", "80" )); - int sslPort = Integer.valueOf(params.getProperty("IntHttpsPort", "443" )); - boolean allowHttp = Boolean.valueOf(params.getProperty("HttpAllowed", "false")); - serverLogger.info( "port params: http=" + httpPort + " https=" + sslPort ); - serverLogger.info( "allowHttp=" + allowHttp ); - String keystore=null; - String keystorePwd = null; - String keyPwd = null; - - // HTTP Server - HttpConfiguration http_config = new HttpConfiguration(); - http_config.setSecureScheme("https"); - http_config.setSecurePort(sslPort); - http_config.setOutputBufferSize(32768); + public Server getServer() { + return server; + } - - - try(ServerConnector httpConnector = new ServerConnector(server, new HttpConnectionFactory(http_config))) { - httpConnector.setPort(httpPort); - httpConnector.setIdleTimeout(30000); + public JettyServer(Properties params) throws Exception { + server = new Server(); + int httpPort = Integer.valueOf(params.getProperty("IntHttpPort", "80")); + int sslPort = Integer.valueOf(params.getProperty("IntHttpsPort", "443")); + boolean allowHttp = Boolean.valueOf(params.getProperty("HttpAllowed", "false")); + serverLogger.info("port params: http=" + httpPort + " https=" + sslPort); + serverLogger.info("allowHttp=" + allowHttp); - // HTTPS Server + // HTTP Server + HttpConfiguration http_config = new HttpConfiguration(); + http_config.setSecureScheme("https"); + http_config.setSecurePort(sslPort); + http_config.setOutputBufferSize(32768); - HttpConfiguration https_config = new HttpConfiguration(http_config); - https_config.addCustomizer(new SecureRequestCustomizer()); - SslContextFactory sslContextFactory = new SslContextFactory(); - keystore = params.getProperty("KeyStoreFile", "etc/keystore"); - logger.info("https Server using keystore at " + keystore); - keystorePwd = params.getProperty("KeyStorePassword", "changeit"); - keyPwd = params.getProperty("KeyPassword", "changeit"); + try (ServerConnector httpConnector = new ServerConnector(server, new HttpConnectionFactory(http_config))) { + httpConnector.setPort(httpPort); + httpConnector.setIdleTimeout(30000); + // HTTPS Server - sslContextFactory.setKeyStorePath(keystore); - sslContextFactory.setKeyStorePassword(keystorePwd); - sslContextFactory.setKeyManagerPassword(keyPwd); + HttpConfiguration https_config = new HttpConfiguration(http_config); + https_config.addCustomizer(new SecureRequestCustomizer()); + SslContextFactory sslContextFactory = new SslContextFactory(); + sslContextFactory.setWantClientAuth(true); + setUpKeystore(params, sslContextFactory); + setUpTrustStore(params, sslContextFactory); - if (sslPort != 0) { - try(ServerConnector sslConnector = new ServerConnector(server, - new SslConnectionFactory(sslContextFactory, "http/1.1"), - new HttpConnectionFactory(https_config))) { + if (sslPort != 0) { + try (ServerConnector sslConnector = new ServerConnector(server, + new SslConnectionFactory(sslContextFactory, "http/1.1"), + new HttpConnectionFactory(https_config))) { sslConnector.setPort(sslPort); if (allowHttp) { logger.info("Starting httpConnector on port " + httpPort); @@ -102,47 +92,71 @@ public class JettyServer extends BaseLoggingClass { server.setConnectors(new Connector[]{sslConnector}); } } - } else { - serverLogger.info("NOT starting sslConnector on port " + sslPort + " for https"); - if (allowHttp) { - serverLogger.info("Starting httpConnector on port " + httpPort); - server.setConnectors(new Connector[]{httpConnector}); - } - } - } - + } else { + serverLogger.info("NOT starting sslConnector on port " + sslPort + " for https"); + if (allowHttp) { + serverLogger.info("Starting httpConnector on port " + httpPort); + server.setConnectors(new Connector[]{httpConnector}); + } + } + } + // Set context for servlet. This is shared for http and https - ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS); - context.setContextPath("/"); - server.setHandler( context ); + ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS); + context.setContextPath("/"); + server.setHandler(context); - ServletHolder jerseyServlet = context.addServlet( org.glassfish.jersey.servlet.ServletContainer.class, "/webapi/*"); + ServletHolder jerseyServlet = context + .addServlet(org.glassfish.jersey.servlet.ServletContainer.class, "/webapi/*"); jerseyServlet.setInitOrder(1); - jerseyServlet.setInitParameter("jersey.config.server.provider.packages", "org.onap.dmaap.dbcapi.resources" ); - jerseyServlet.setInitParameter("javax.ws.rs.Application", "org.onap.dmaap.dbcapi.server.ApplicationConfig" ); - + jerseyServlet.setInitParameter("jersey.config.server.provider.packages", "org.onap.dmaap.dbcapi.resources"); + jerseyServlet.setInitParameter("javax.ws.rs.Application", "org.onap.dmaap.dbcapi.server.ApplicationConfig"); + // also serve up some static pages... - ServletHolder staticServlet = context.addServlet(DefaultServlet.class,"/*"); - staticServlet.setInitParameter("resourceBase","www"); - staticServlet.setInitParameter("pathInfoOnly","true"); + ServletHolder staticServlet = context.addServlet(DefaultServlet.class, "/*"); + staticServlet.setInitParameter("resourceBase", "www"); + staticServlet.setInitParameter("pathInfoOnly", "true"); + + registerAuthFilters(context); try { serverLogger.info("Starting jetty server"); - String unit_test = params.getProperty("UnitTest", "No"); + String unit_test = params.getProperty("UnitTest", "No"); serverLogger.info("UnitTest=" + unit_test); - if ( unit_test.equals( "No" ) ) { - server.start(); - server.dumpStdErr(); - server.join(); - } - } catch ( Exception e ) { - errorLogger.error( "Exception " + e ); - errorLogger.error( "possibly unable to use keystore " + keystore + " with passwords " + keystorePwd + " and " + keyPwd ); - //System.exit(1); + if (unit_test.equals("No")) { + server.start(); + server.dumpStdErr(); + server.join(); + } + } catch (Exception e) { + errorLogger.error("Exception " + e); } finally { - server.destroy(); + server.destroy(); } - + + } + + private void registerAuthFilters(ServletContextHandler context) { + context.addFilter("org.onap.dmaap.dbcapi.resources.AAFAuthenticationFilter", "/webapi/*", + Sets.newEnumSet(Sets.newHashSet(DispatcherType.FORWARD, DispatcherType.REQUEST), DispatcherType.class)); + context.addFilter("org.onap.dmaap.dbcapi.resources.AAFAuthorizationFilter", "/webapi/*", + Sets.newEnumSet(Sets.newHashSet(DispatcherType.FORWARD, DispatcherType.REQUEST), DispatcherType.class)); + } + + private void setUpKeystore(Properties params, SslContextFactory sslContextFactory) { + String keystore = params.getProperty("KeyStoreFile", "etc/keystore"); + logger.info("https Server using keystore at " + keystore); + sslContextFactory.setKeyStorePath(keystore); + sslContextFactory.setKeyStorePassword(params.getProperty("KeyStorePassword", "changeit")); + sslContextFactory.setKeyManagerPassword(params.getProperty("KeyPassword", "changeit")); + } + + private void setUpTrustStore(Properties params, SslContextFactory sslContextFactory) { + String truststore = params.getProperty("TrustStoreFile", "etc/org.onap.dmaap-bc.trust.jks"); + logger.info("https Server using truststore at " + truststore); + sslContextFactory.setTrustStorePath(truststore); + sslContextFactory.setTrustStoreType(params.getProperty("TrustStoreType", "jks")); + sslContextFactory.setTrustStorePassword(params.getProperty("TrustStorePassword", "changeit")); } } diff --git a/src/main/java/org/onap/dmaap/dbcapi/server/Main.java b/src/main/java/org/onap/dmaap/dbcapi/server/Main.java index d8ee278..906337a 100644 --- a/src/main/java/org/onap/dmaap/dbcapi/server/Main.java +++ b/src/main/java/org/onap/dmaap/dbcapi/server/Main.java @@ -62,7 +62,7 @@ public class Main extends BaseLoggingClass { MDC.put(MDC_SERVER_FQDN, InetAddress.getLocalHost().getHostName()); MDC.put(MDC_SERVER_IP_ADDRESS, InetAddress.getLocalHost().getHostAddress()); } catch (Exception e) { - e.printStackTrace(); + errorLogger.error("Error while getting hostname or address", e); } MDC.put(MDC_INSTANCE_UUID, UUID.randomUUID().toString()); MDC.put(MDC_ALERT_SEVERITY, "0"); diff --git a/src/main/java/org/onap/dmaap/dbcapi/service/ApiService.java b/src/main/java/org/onap/dmaap/dbcapi/service/ApiService.java index 48f81db..e1beb28 100644 --- a/src/main/java/org/onap/dmaap/dbcapi/service/ApiService.java +++ b/src/main/java/org/onap/dmaap/dbcapi/service/ApiService.java @@ -7,9 +7,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -20,322 +20,153 @@ package org.onap.dmaap.dbcapi.service; -import static com.att.eelf.configuration.Configuration.MDC_BEGIN_TIMESTAMP; -import static com.att.eelf.configuration.Configuration.MDC_ELAPSED_TIME; -import static com.att.eelf.configuration.Configuration.MDC_END_TIMESTAMP; import static com.att.eelf.configuration.Configuration.MDC_KEY_REQUEST_ID; import static com.att.eelf.configuration.Configuration.MDC_PARTNER_NAME; -import static com.att.eelf.configuration.Configuration.MDC_RESPONSE_CODE; -import static com.att.eelf.configuration.Configuration.MDC_RESPONSE_DESC; import static com.att.eelf.configuration.Configuration.MDC_SERVICE_NAME; -import static com.att.eelf.configuration.Configuration.MDC_STATUS_CODE; -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.TimeZone; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import javax.ws.rs.core.Response; -import javax.ws.rs.core.Response.Status; import javax.xml.bind.DatatypeConverter; - import org.onap.dmaap.dbcapi.aaf.DmaapPerm; import org.onap.dmaap.dbcapi.authentication.ApiPolicy; import org.onap.dmaap.dbcapi.authentication.AuthenticationErrorException; import org.onap.dmaap.dbcapi.logging.BaseLoggingClass; import org.onap.dmaap.dbcapi.model.ApiError; import org.onap.dmaap.dbcapi.model.Dmaap; -import org.onap.dmaap.dbcapi.resources.RequiredFieldException; import org.onap.dmaap.dbcapi.util.DmaapConfig; import org.onap.dmaap.dbcapi.util.RandomString; import org.slf4j.MDC; public class ApiService extends BaseLoggingClass { - private class StopWatch { - private long clock = 0; - private long elapsed = 0; - - - - public StopWatch() { - clock = 0; - elapsed = 0; - } - - public void reset() { - clock = System.currentTimeMillis(); - elapsed = 0; - } - public void stop() { - Long stopTime = System.currentTimeMillis(); - elapsed += stopTime - clock; - clock = 0; - MDC.put( MDC_END_TIMESTAMP, isoFormatter.format(new Date(stopTime))); - MDC.put( MDC_ELAPSED_TIME, String.valueOf(elapsed)); - } - public void start() { - if ( clock != 0 ) { - //not stopped - return; - } - clock = System.currentTimeMillis(); - MDC.put( MDC_BEGIN_TIMESTAMP, isoFormatter.format(new Date(clock))); - } - private long getElapsed() { - return elapsed; - } - } - - private String apiNamespace; - - private String uri; - private String uriPath; - private String method; - private String authorization; - private String requestId; - private ApiError err; - private StopWatch stopwatch; - private ApiPolicy apiPolicy; - - public static final String ISO_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"; - public final static TimeZone utc = TimeZone.getTimeZone("UTC"); - public final static SimpleDateFormat isoFormatter = new SimpleDateFormat(ISO_FORMAT); - - static { - isoFormatter.setTimeZone(utc); - } - public ApiService() { - - stopwatch = new StopWatch(); - stopwatch.start(); - err = new ApiError(); - requestId = (new RandomString(10)).nextString(); - - if (apiNamespace == null) { - DmaapConfig p = (DmaapConfig)DmaapConfig.getConfig(); - apiNamespace = p.getProperty("ApiNamespace", "org.openecomp.dmaapBC.api"); - logger.info( "config param usePE has been deprecated. Use ApiPermission.Class property instead."); - } - apiPolicy = new ApiPolicy(); - - logger.info( "apiNamespace=" + apiNamespace); - } - - public ApiService setAuth( String auth ) { - this.authorization = auth; - logger.info( "setAuth: authorization={} ", authorization); - return this; - } - private void setServiceName(){ - String svcRequest = new String( this.method + " " + this.uriPath ); - MDC.put(MDC_SERVICE_NAME, svcRequest ); - } - public ApiService setHttpMethod( String httpMethod ) { - this.method = httpMethod; - logger.info( "setHttpMethod: method={} ", method); - setServiceName(); - return this; - } - public ApiService setUriPath( String uriPath ) { - this.uriPath = uriPath; - this.uri = setUriFromPath( uriPath ); - logger.info( "setUriPath: uriPath={} uri={}", uriPath, uri); - setServiceName(); - return this; - } - private String setUriFromPath( String uriPath ) { - int ch = uriPath.indexOf("/"); - if ( ch > 0 ) { - return( (String) uriPath.subSequence(0, ch ) ); - } else { - return uriPath; - } - } - - public ApiError getErr() { - return err; - } - - - public void setErr(ApiError err) { - this.err = err; - } - - - // test for presence of a required field - public void required( String name, Object val, String expr ) throws RequiredFieldException { - err.setCode(0); - if ( val == null ) { - err.setCode(Status.BAD_REQUEST.getStatusCode()); - err.setMessage("missing required field"); - err.setFields( name ); - throw new RequiredFieldException(); - } - if ( expr != null && ! expr.isEmpty() ) { - Pattern pattern = Pattern.compile(expr); - Matcher matcher = pattern.matcher((CharSequence) val); - if ( ! matcher.find() ) { - err.setCode(Status.BAD_REQUEST.getStatusCode()); - err.setMessage( "value '" + val + "' violates regexp check '" + expr + "'"); - err.setFields( name ); - throw new RequiredFieldException(); - } - } - } - - // utility to serialize ApiErr object - public String toString() { - return String.format( "code=%d msg=%s fields=%s", err.getCode(), err.getMessage(), err.getFields() ); - } - - public void setCode(int statusCode) { - err.setCode(statusCode); - } - - - public void setMessage(String string) { - err.setMessage(string); - } - - - public void setFields(String string) { - err.setFields(string); - } - - private Response buildResponse( Object obj ) { - stopwatch.stop(); - MDC.put( MDC_RESPONSE_CODE, String.valueOf(err.getCode()) ); - - auditLogger.auditEvent( "" ); - return Response.status( err.getCode()) - .entity(obj) - .build(); - } - private Response buildSuccessResponse(Object d) { - MDC.put( MDC_STATUS_CODE, "COMPLETE"); - MDC.put( MDC_RESPONSE_DESC, ""); - return buildResponse( d ); - } - private Response buildErrResponse() { - - MDC.put( MDC_STATUS_CODE, "ERROR"); - MDC.put( MDC_RESPONSE_DESC, err.getMessage()); - - return buildResponse(getErr()); - } - public Response success( Object d ) { - err.setCode(Status.OK.getStatusCode()); - return buildSuccessResponse(d); - - } - public Response success( int code, Object d ) { - err.setCode(code); - return buildSuccessResponse(d); - } - - public Response unauthorized( String msg ) { - err.setCode(Status.UNAUTHORIZED.getStatusCode()); - err.setFields( "Authorization"); - err.setMessage( msg ); - return buildErrResponse(); - } - public Response unauthorized() { - err.setCode(Status.UNAUTHORIZED.getStatusCode()); - err.setFields( "Authorization"); - err.setMessage( "User credentials in HTTP Header field Authorization are not authorized for the requested action"); - return buildErrResponse(); - } - public Response unavailable() { - err.setCode(Status.SERVICE_UNAVAILABLE.getStatusCode()); - err.setMessage( "Request is unavailable due to unexpected condition"); - return buildErrResponse(); - } - public Response notFound() { - err.setCode(Status.NOT_FOUND.getStatusCode()); - err.setMessage( "Requested object not found"); - return buildErrResponse(); - } - public Response error() { - return buildErrResponse(); - } - - public void checkAuthorization( String auth, String uriPath, String httpMethod ) throws AuthenticationErrorException, Exception { - authorization = auth; - setUriFromPath( uriPath ); - method = httpMethod; - - checkAuthorization(); - } - - - public void checkAuthorization() throws AuthenticationErrorException, Exception { - - MDC.put(MDC_KEY_REQUEST_ID, requestId); - - logger.info("request: uri={} method={} auth={}", uri, method, authorization ); - - if ( uri == null || uri.isEmpty()) { - String errmsg = "No URI value provided "; - err.setMessage(errmsg); - logger.info( errmsg ); - throw new AuthenticationErrorException( ); - } - if ( method == null || method.isEmpty()) { - String errmsg = "No method value provided "; - err.setMessage(errmsg); - logger.info( errmsg ); - throw new AuthenticationErrorException( ); - } - DmaapService dmaapService = new DmaapService(); - Dmaap dmaap = dmaapService.getDmaap(); - String env = dmaap.getDmaapName(); - - // special case during bootstrap of app when DMaaP environment may not be set. - // this allows us to authorize certain APIs used for initialization during this window. - if ( env == null || env.isEmpty() ) { - env = "boot"; - } - if ( ! apiPolicy.getUseAuthClass() ) return; // skip authorization if not enabled - if ( authorization == null || authorization.isEmpty()) { - String errmsg = "No basic authorization value provided "; - err.setMessage(errmsg); - logger.info( errmsg ); - throw new AuthenticationErrorException( ); - } - String credentials = authorization.substring("Basic".length()).trim(); + private String apiNamespace; + private String uri; + private String uriPath; + private String method; + private String authorization; + private String requestId; + private ApiError err; + private ApiPolicy apiPolicy; + + public ApiService() { + + err = new ApiError(); + requestId = (new RandomString(10)).nextString(); + + if (apiNamespace == null) { + DmaapConfig p = (DmaapConfig) DmaapConfig.getConfig(); + apiNamespace = p.getProperty("ApiNamespace", "org.openecomp.dmaapBC.api"); + logger.info("config param usePE has been deprecated. Use ApiPermission.Class property instead."); + } + apiPolicy = new ApiPolicy(); + + logger.info("apiNamespace=" + apiNamespace); + } + + public ApiService setAuth(String auth) { + this.authorization = auth; + logger.info("setAuth: authorization={} ", authorization); + return this; + } + + private void setServiceName() { + String svcRequest = new String(this.method + " " + this.uriPath); + MDC.put(MDC_SERVICE_NAME, svcRequest); + } + + public ApiService setHttpMethod(String httpMethod) { + this.method = httpMethod; + logger.info("setHttpMethod: method={} ", method); + setServiceName(); + return this; + } + + public ApiService setUriPath(String uriPath) { + this.uriPath = uriPath; + this.uri = setUriFromPath(uriPath); + logger.info("setUriPath: uriPath={} uri={}", uriPath, uri); + setServiceName(); + return this; + } + + private String setUriFromPath(String uriPath) { + int ch = uriPath.indexOf("/"); + if (ch > 0) { + return ((String) uriPath.subSequence(0, ch)); + } else { + return uriPath; + } + } + + public ApiError getErr() { + return err; + } + + public void checkAuthorization() throws Exception { + + MDC.put(MDC_KEY_REQUEST_ID, requestId); + + logger.info("request: uri={} method={} auth={}", uri, method, authorization); + + if (uri == null || uri.isEmpty()) { + String errmsg = "No URI value provided "; + err.setMessage(errmsg); + logger.info(errmsg); + throw new AuthenticationErrorException(); + } + if (method == null || method.isEmpty()) { + String errmsg = "No method value provided "; + err.setMessage(errmsg); + logger.info(errmsg); + throw new AuthenticationErrorException(); + } + DmaapService dmaapService = new DmaapService(); + Dmaap dmaap = dmaapService.getDmaap(); + String env = dmaap.getDmaapName(); + + // special case during bootstrap of app when DMaaP environment may not be set. + // this allows us to authorize certain APIs used for initialization during this window. + if (env == null || env.isEmpty()) { + env = "boot"; + } + if (!apiPolicy.getUseAuthClass()) { + return; // skip authorization if not enabled + } + if (authorization == null || authorization.isEmpty()) { + String errmsg = "No basic authorization value provided "; + err.setMessage(errmsg); + logger.info(errmsg); + throw new AuthenticationErrorException(); + } + String credentials = authorization.substring("Basic".length()).trim(); byte[] decoded = DatatypeConverter.parseBase64Binary(credentials); String decodedString = new String(decoded); String[] actualCredentials = decodedString.split(":"); String ID = actualCredentials[0]; String Password = actualCredentials[1]; MDC.put(MDC_PARTNER_NAME, ID); - try { - - DmaapPerm p = new DmaapPerm( apiNamespace + "." + uri, env, method ); - apiPolicy.check( ID, Password, p); - } catch ( AuthenticationErrorException ae ) { - String errmsg = "User " + ID + " failed authentication/authorization for " + apiNamespace + "." + uriPath + " " + env + " " + method; - logger.info( errmsg ); - err.setMessage(errmsg); - throw ae; - - } - - - } - public String getRequestId() { - return requestId; - } - public ApiService setRequestId(String requestId) { - if ( requestId == null || requestId.isEmpty()) { - this.requestId = (new RandomString(10)).nextString(); - logger.warn( "X-ECOMP-RequestID not set in HTTP Header. Setting RequestId value to: " + this.requestId ); - } else { - this.requestId = requestId; - } - MDC.put(MDC_KEY_REQUEST_ID, this.requestId); - return this; - } + try { + + DmaapPerm p = new DmaapPerm(apiNamespace + "." + uri, env, method); + apiPolicy.check(ID, Password, p); + } catch (AuthenticationErrorException ae) { + String errmsg = + "User " + ID + " failed authentication/authorization for " + apiNamespace + "." + uriPath + " " + env + + " " + method; + logger.info(errmsg); + err.setMessage(errmsg); + throw ae; + + } + } + + public ApiService setRequestId(String requestId) { + if (requestId == null || requestId.isEmpty()) { + this.requestId = (new RandomString(10)).nextString(); + logger.warn("X-ECOMP-RequestID not set in HTTP Header. Setting RequestId value to: " + this.requestId); + } else { + this.requestId = requestId; + } + MDC.put(MDC_KEY_REQUEST_ID, this.requestId); + return this; + } } + diff --git a/src/main/java/org/onap/dmaap/dbcapi/service/DR_NodeService.java b/src/main/java/org/onap/dmaap/dbcapi/service/DR_NodeService.java index b478dca..9181154 100644 --- a/src/main/java/org/onap/dmaap/dbcapi/service/DR_NodeService.java +++ b/src/main/java/org/onap/dmaap/dbcapi/service/DR_NodeService.java @@ -215,11 +215,11 @@ public class DR_NodeService extends BaseLoggingClass { } public DR_Node updateDr_Node( DR_Node node, ApiError apiError ) { - DR_Node old = dr_nodes.get( node ); + DR_Node old = dr_nodes.get( node.getFqdn() ); if ( old == null ) { apiError.setCode(Status.NOT_FOUND.getStatusCode()); apiError.setFields( "fqdn"); - apiError.setMessage( "Node " + node + " does not exist"); + apiError.setMessage( "Node " + node.getFqdn() + " does not exist"); return null; } node.setLastMod(); diff --git a/src/main/java/org/onap/dmaap/dbcapi/service/DR_PubService.java b/src/main/java/org/onap/dmaap/dbcapi/service/DR_PubService.java index 13717da..eb5b514 100644 --- a/src/main/java/org/onap/dmaap/dbcapi/service/DR_PubService.java +++ b/src/main/java/org/onap/dmaap/dbcapi/service/DR_PubService.java @@ -129,7 +129,11 @@ public class DR_PubService extends BaseLoggingClass{ } public DR_Pub removeDr_Pub( String pubId, ApiError err ) { - + return removeDr_Pub( pubId, err, true ); + } + + + public DR_Pub removeDr_Pub( String pubId, ApiError err, boolean hitDR ) { DR_Pub pub = dr_pubs.get( pubId ); if ( pub == null ) { err.setCode(Status.NOT_FOUND.getStatusCode()); diff --git a/src/main/java/org/onap/dmaap/dbcapi/service/DR_SubService.java b/src/main/java/org/onap/dmaap/dbcapi/service/DR_SubService.java index 9d233a5..0a583a0 100644 --- a/src/main/java/org/onap/dmaap/dbcapi/service/DR_SubService.java +++ b/src/main/java/org/onap/dmaap/dbcapi/service/DR_SubService.java @@ -173,6 +173,11 @@ public class DR_SubService extends BaseLoggingClass { } public void removeDr_Sub( String key, ApiError apiError ) { + removeDr_Sub( key, apiError, true ); + return; + } + + public void removeDr_Sub( String key, ApiError apiError, boolean hitDR ) { logger.debug( "enter removeDR_Subs()"); DR_Sub sub = dr_subs.get( key ); @@ -180,11 +185,15 @@ public class DR_SubService extends BaseLoggingClass { apiError.setCode(Status.NOT_FOUND.getStatusCode()); apiError.setFields( "subId"); apiError.setMessage("subId " + key + " not found"); - } else { - DrProvConnection prov = new DrProvConnection(); - prov.makeSubPutConnection( key ); - String resp = prov.doDeleteDr_Sub( sub, apiError ); - logger.debug( "resp=" + resp ); + } else { + if ( hitDR ) { + DrProvConnection prov = new DrProvConnection(); + prov.makeSubPutConnection( key ); + String resp = prov.doDeleteDr_Sub( sub, apiError ); + logger.debug( "resp=" + resp ); + } else { + apiError.setCode(200); + } if ( apiError.is2xx() || unit_test.equals( "Yes" ) ) { dr_subs.remove(key); @@ -209,8 +218,8 @@ public class DR_SubService extends BaseLoggingClass { server, subid, sub.getUsername(), sub.getUserpwd()); String links = String.format( "\"links\": {\"feed\": \"https://dr-prov/feedlog/%s\", \"self\": \"https://dr-prov/sub/%s\", \"log\": \"https://dr-prov/sublog/%s\" }", sub.getFeedId(), - sub.getSubId(), - sub.getSubId() ); + subid, + subid ); ret += links + "}"; logger.info( "DR_SubService:simulateResp=" + ret); diff --git a/src/main/java/org/onap/dmaap/dbcapi/service/FeedService.java b/src/main/java/org/onap/dmaap/dbcapi/service/FeedService.java index de18d95..77d11ab 100644 --- a/src/main/java/org/onap/dmaap/dbcapi/service/FeedService.java +++ b/src/main/java/org/onap/dmaap/dbcapi/service/FeedService.java @@ -25,12 +25,17 @@ package org.onap.dmaap.dbcapi.service; import org.onap.dmaap.dbcapi.util.RandomInteger; import java.util.ArrayList; +import java.util.Iterator; import java.util.List; import java.util.Map; import javax.ws.rs.core.Response.Status; import org.apache.log4j.Logger; +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; +import org.json.simple.parser.JSONParser; +import org.json.simple.parser.ParseException; import org.onap.dmaap.dbcapi.client.DrProvConnection; import org.onap.dmaap.dbcapi.database.DatabaseClass; import org.onap.dmaap.dbcapi.logging.BaseLoggingClass; @@ -38,12 +43,14 @@ import org.onap.dmaap.dbcapi.model.ApiError; import org.onap.dmaap.dbcapi.model.DR_Pub; import org.onap.dmaap.dbcapi.model.DR_Sub; import org.onap.dmaap.dbcapi.model.Feed; +import org.onap.dmaap.dbcapi.model.MR_Client; import org.onap.dmaap.dbcapi.model.DmaapObject.DmaapObject_Status; import org.onap.dmaap.dbcapi.util.DmaapConfig; public class FeedService extends BaseLoggingClass { private Map<String, Feed> feeds = DatabaseClass.getFeeds(); + private Map<String, DR_Sub> dr_subs = DatabaseClass.getDr_subs(); private DR_PubService pubService = new DR_PubService(); private DR_SubService subService = new DR_SubService(); private DcaeLocationService dcaeLocations = new DcaeLocationService(); @@ -68,6 +75,10 @@ public class FeedService extends BaseLoggingClass { ArrayList<DR_Sub> subs = subService.getDr_SubsByFeedId( f.getFeedId() ); f.setSubs(subs); } + + public List<Feed> getAllFeeds(){ + return getAllFeeds(null, null, null); + } public List<Feed> getAllFeeds( String name, String ver, String match ) { logger.info( "getAllFeeds: name=" + name + " ver=" + ver + " match=" + match); @@ -351,22 +362,30 @@ public class FeedService extends BaseLoggingClass { // 2) Call the DR Delete function. Feed with the same name and version can never be added again // public Feed removeFeed( Feed req, ApiError err ) { + return removeFeed( req, err, true ); + } + + public Feed removeFeed( Feed req, ApiError err, boolean hitDR ) { // strip pubs and subs from feed first no matter what ArrayList<DR_Pub> pubs = pubService.getDr_PubsByFeedId( req.getFeedId() ); for( DR_Pub pub: pubs ) { - pubService.removeDr_Pub(pub.getPubId(), err); + pubService.removeDr_Pub(pub.getPubId(), err, hitDR); if ( ! err.is2xx()) { return req; } } ArrayList<DR_Sub> subs = subService.getDr_SubsByFeedId( req.getFeedId() ); for ( DR_Sub sub: subs ) { - subService.removeDr_Sub(sub.getSubId(), err); + subService.removeDr_Sub(sub.getSubId(), err, hitDR); if ( ! err.is2xx()) { return req; } } + + if ( ! hitDR ) { + return feeds.remove(req.getFeedId()); + } if ( deleteHandling.equalsIgnoreCase("DeleteOnDR")) { DrProvConnection prov = new DrProvConnection(); @@ -415,6 +434,92 @@ public class FeedService extends BaseLoggingClass { } + + + /* + * sync will retrieve current config from DR and add it to the DB + * when hard = true, then first git rid of current DR provisioning data (from the DB) + */ + public void sync( boolean hard, ApiError err ) { + + if ( hard ) { + + ArrayList<Feed> flist = new ArrayList<Feed>(this.getAllFeeds()); + for ( Iterator<Feed> it = flist.iterator(); it.hasNext(); ) { + Feed f = it.next(); + + @SuppressWarnings("unused") + Feed old = removeFeed( f, err, false ); + if (! err.is2xx()) { + return; + } + } + } + + DrProvConnection prov = new DrProvConnection(); + prov.makeDumpConnection(); + String resp = prov.doGetDump( err ); + if (! err.is2xx()) { + return; + } + logger.debug("sync: resp from DR is: " + resp); + + JSONParser parser = new JSONParser(); + JSONObject jsonObj; + try { + jsonObj = (JSONObject) parser.parse( resp ); + } catch ( ParseException pe ) { + logger.error( "Error parsing provisioning data: " + resp ); + err.setCode(500); + return; + } + + int i; + + JSONArray feedsArray = (JSONArray) jsonObj.get( "feeds"); + for( i = 0; i < feedsArray.size(); i++ ) { + JSONObject entry = (JSONObject) feedsArray.get(i); + Feed fnew = new Feed( entry.toJSONString() ); + + logger.info( "fnew status is:" + fnew.getStatus() ); + if ( ! fnew.isStatusValid()) { + err.setCode(500); + err.setMessage( "Unexpected response from DR backend" ); + err.setFields("response"); + return; + } + + if ( ! savePubs( fnew ) ) { + err.setCode(Status.BAD_REQUEST.getStatusCode()); + err.setMessage("Unable to save Pub or Sub objects"); + return; + } + fnew.setFormatUuid(fnew.getFormatUuid()); + fnew.setLastMod(); + feeds.put( fnew.getFeedId(), fnew ); + + } + + JSONArray subArray = (JSONArray) jsonObj.get( "subscriptions"); + for( i = 0; i < subArray.size(); i++ ) { + JSONObject entry = (JSONObject) subArray.get(i); + DR_Sub snew = new DR_Sub( entry.toJSONString() ); + + logger.info( "snew status is:" + snew.getStatus() ); + if ( ! snew.isStatusValid()) { + err.setCode(500); + err.setMessage( "Unexpected response from DR backend" ); + err.setFields("response"); + return; + } + + dr_subs.put( snew.getSubId(), snew ); + + } + err.setCode(200); + return; + + } private String simulateResp( Feed f, String action ){ String server = "localhost"; diff --git a/src/main/java/org/onap/dmaap/dbcapi/service/MirrorMakerService.java b/src/main/java/org/onap/dmaap/dbcapi/service/MirrorMakerService.java index da9d822..5d695f4 100644 --- a/src/main/java/org/onap/dmaap/dbcapi/service/MirrorMakerService.java +++ b/src/main/java/org/onap/dmaap/dbcapi/service/MirrorMakerService.java @@ -57,6 +57,7 @@ public class MirrorMakerService extends BaseLoggingClass { private static String defaultConsumerPort; private static String centralFqdn; private int maxTopicsPerMM; + private boolean mmPerMR; public MirrorMakerService() { super(); @@ -68,6 +69,7 @@ public class MirrorMakerService extends BaseLoggingClass { defaultConsumerPort = p.getProperty( "MR.TargetReplicationPort", "2181"); centralFqdn = p.getProperty("MR.CentralCname", "notSet"); maxTopicsPerMM = Integer.valueOf( p.getProperty( "MaxTopicsPerMM", "5")); + mmPerMR = "true".equalsIgnoreCase(p.getProperty("MirrorMakerPerMR", "true")); } // will create a MM on MMagent if needed @@ -79,34 +81,43 @@ public class MirrorMakerService extends BaseLoggingClass { DmaapService dmaap = new DmaapService(); MR_ClusterService clusters = new MR_ClusterService(); - - // in 1610, MM should only exist for edge-to-central - // we use a cname for the central MR cluster that is active, and provision on agent topic on that target - // but only send 1 message so MM Agents can read it relying on kafka delivery - for( MR_Cluster central: clusters.getCentralClusters() ) { - prov.makeTopicConnection(central, dmaap.getBridgeAdminFqtn(), centralFqdn ); - ApiError resp = prov.doPostMessage(mm.createMirrorMaker( defaultConsumerPort, defaultProducerPort )); - if ( ! resp.is2xx() ) { - - errorLogger.error( DmaapbcLogMessageEnum.MM_PUBLISH_ERROR, "create MM", Integer.toString(resp.getCode()), resp.getMessage()); - mm.setStatus(DmaapObject_Status.INVALID); - } else { - prov.makeTopicConnection(central, dmaap.getBridgeAdminFqtn(), centralFqdn ); - resp = prov.doPostMessage(mm.getWhitelistUpdateJSON()); - if ( ! resp.is2xx()) { - errorLogger.error( DmaapbcLogMessageEnum.MM_PUBLISH_ERROR,"MR Bridge", Integer.toString(resp.getCode()), resp.getMessage()); - mm.setStatus(DmaapObject_Status.INVALID); - } else { - mm.setStatus(DmaapObject_Status.VALID); - } - } - - // we only want to send one message even if there are multiple central clusters - break; + MR_Cluster target_cluster = null; + String override = null; - } + if ( ! mmPerMR ) { + // in ECOMP, MM Agent is only deployed at central, so this case is needed for backwards compatibility + // we use a cname for the central MR cluster that is active, and provision on agent topic on that target + // but only send 1 message so MM Agents can read it relying on kafka delivery + for( MR_Cluster cluster: clusters.getCentralClusters() ) { + + target_cluster = cluster; + override = centralFqdn; + // we only want to send one message even if there are multiple central clusters + break; + + } + } else { + // In ONAP deployment architecture, the MM Agent is deployed with each target MR + target_cluster = clusters.getMr_ClusterByFQDN(mm.getTargetCluster()); + override = null; + } + prov.makeTopicConnection(target_cluster, dmaap.getBridgeAdminFqtn(), override ); + ApiError resp = prov.doPostMessage(mm.createMirrorMaker( defaultConsumerPort, defaultProducerPort )); + if ( ! resp.is2xx() ) { + errorLogger.error( DmaapbcLogMessageEnum.MM_PUBLISH_ERROR, "create MM", Integer.toString(resp.getCode()), resp.getMessage()); + mm.setStatus(DmaapObject_Status.INVALID); + } else { + prov.makeTopicConnection(target_cluster, dmaap.getBridgeAdminFqtn(), override ); + resp = prov.doPostMessage(mm.getWhitelistUpdateJSON()); + if ( ! resp.is2xx()) { + errorLogger.error( DmaapbcLogMessageEnum.MM_PUBLISH_ERROR,"MR Bridge", Integer.toString(resp.getCode()), resp.getMessage()); + mm.setStatus(DmaapObject_Status.INVALID); + } else { + mm.setStatus(DmaapObject_Status.VALID); + } + } mm.setLastMod(); return mirrors.put( mm.getMmName(), mm); diff --git a/src/main/java/org/onap/dmaap/dbcapi/service/TopicService.java b/src/main/java/org/onap/dmaap/dbcapi/service/TopicService.java index eeffa5b..a7991e8 100644 --- a/src/main/java/org/onap/dmaap/dbcapi/service/TopicService.java +++ b/src/main/java/org/onap/dmaap/dbcapi/service/TopicService.java @@ -42,7 +42,6 @@ import org.onap.dmaap.dbcapi.logging.BaseLoggingClass; import org.onap.dmaap.dbcapi.logging.DmaapbcLogMessageEnum; import org.onap.dmaap.dbcapi.model.ApiError; import org.onap.dmaap.dbcapi.model.DcaeLocation; -import org.onap.dmaap.dbcapi.model.Dmaap; import org.onap.dmaap.dbcapi.model.DmaapObject.DmaapObject_Status; import org.onap.dmaap.dbcapi.model.MR_Client; import org.onap.dmaap.dbcapi.model.MR_Cluster; @@ -70,6 +69,8 @@ public class TopicService extends BaseLoggingClass { private static String centralCname; private static boolean createTopicRoles; + private boolean strictGraph = true; + private boolean mmPerMR; public TopicService(){ @@ -77,11 +78,15 @@ public class TopicService extends BaseLoggingClass { defaultGlobalMrHost = p.getProperty("MR.globalHost", "global.host.not.set"); centralCname = p.getProperty("MR.CentralCname"); createTopicRoles = "true".equalsIgnoreCase(p.getProperty("aaf.CreateTopicRoles", "true")); - - + String unit_test = p.getProperty( "UnitTest", "No" ); + if ( unit_test.equals( "Yes" ) ) { + strictGraph = false; + } + mmPerMR = "true".equalsIgnoreCase(p.getProperty("MirrorMakerPerMR", "true")); logger.info( "TopicService properties: CentralCname=" + centralCname + " defaultGlobarlMrHost=" + defaultGlobalMrHost + - " createTopicRoles=" + createTopicRoles ); + " createTopicRoles=" + createTopicRoles + + " mmPerMR=" + mmPerMR ); } public Map<String, Topic> getTopics() { @@ -299,10 +304,13 @@ public class TopicService extends BaseLoggingClass { public Topic updateTopic( Topic topic, ApiError err ) { - logger.info( "Entry: updateTopic"); + logger.info( "updateTopic: entry"); + logger.info( "updateTopic: topic=" + topic); + logger.info( "updateTopic: fqtn=" + topic.getFqtn() ); if ( topic.getFqtn().isEmpty()) { return null; } + logger.info( "updateTopic: call checkForBridge"); Topic ntopic = checkForBridge( topic, err ); if ( ntopic == null ) { topic.setStatus( DmaapObject_Status.INVALID); @@ -311,6 +319,7 @@ public class TopicService extends BaseLoggingClass { } } if(ntopic != null) { + logger.info( "updateTopic: call put"); mr_topics.put( ntopic.getFqtn(), ntopic ); } err.setCode(Status.OK.getStatusCode()); @@ -374,7 +383,8 @@ public class TopicService extends BaseLoggingClass { public Topic checkForBridge( Topic topic, ApiError err ) { - + logger.info( "checkForBridge: entry"); + logger.info( "fqtn=" + topic.getFqtn() + "replicatonType=" + topic.getReplicationCase()); if ( topic.getReplicationCase() == ReplicationType.REPLICATION_NONE ) { topic.setStatus( DmaapObject_Status.VALID); return topic; @@ -384,6 +394,7 @@ public class TopicService extends BaseLoggingClass { Set<String> groups = clusters.getGroups(); for ( String g : groups ) { + logger.info( "buildBridge for " + topic.getFqtn() + " on group" + g); anythingWrong |= buildBridge( topic, err, g ); } if ( anythingWrong ) { @@ -398,19 +409,24 @@ public class TopicService extends BaseLoggingClass { } private boolean buildBridge( Topic topic, ApiError err, String group ) { - + logger.info( "buildBridge: entry"); boolean anythingWrong = false; Graph graph; + logger.info( "buildBridge: strictGraph=" + strictGraph ); if ( group == null || group.isEmpty() ) { - graph = new Graph( topic.getClients(), true ); + graph = new Graph( topic.getClients(), strictGraph ); } else { - graph = new Graph( topic.getClients(), true, group ); + graph = new Graph( topic.getClients(), strictGraph, group ); } + logger.info( "buildBridge: graph=" + graph ); MR_Cluster groupCentralCluster = null; + if ( graph.isEmpty() ) { + logger.info( "buildBridge: graph is empty. return false" ); return false; } else if ( group == null && topic.getReplicationCase().involvesFQDN() ) { + logger.info( "buildBridge: group is null and replicationCaseInvolvesFQDN. return false" ); return false; } else if ( ! graph.hasCentral() ) { logger.warn( "Topic " + topic.getFqtn() + " wants to be " + topic.getReplicationCase() + " but has no central clients"); @@ -438,11 +454,11 @@ public class TopicService extends BaseLoggingClass { case REPLICATION_EDGE_TO_CENTRAL: case REPLICATION_EDGE_TO_CENTRAL_TO_GLOBAL: // NOTE: this is for E2C portion only source = cluster.getFqdn(); - target = centralCname; + target = (mmPerMR)? groupCentralCluster.getFqdn() : centralCname; break; case REPLICATION_CENTRAL_TO_EDGE: case REPLICATION_GLOBAL_TO_CENTRAL_TO_EDGE: // NOTE: this is for C2E portion only - source = centralCname; + source = (mmPerMR) ? groupCentralCluster.getFqdn() : centralCname; target = cluster.getFqdn(); break; case REPLICATION_CENTRAL_TO_GLOBAL: diff --git a/src/main/java/org/onap/dmaap/dbcapi/util/PermissionBuilder.java b/src/main/java/org/onap/dmaap/dbcapi/util/PermissionBuilder.java new file mode 100644 index 0000000..44c94af --- /dev/null +++ b/src/main/java/org/onap/dmaap/dbcapi/util/PermissionBuilder.java @@ -0,0 +1,86 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2019 Nokia Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.dmaap.dbcapi.util; + +import javax.servlet.http.HttpServletRequest; +import org.onap.dmaap.dbcapi.model.Dmaap; +import org.onap.dmaap.dbcapi.service.DmaapService; + +public class PermissionBuilder { + + static final String API_NS_PROP = "ApiNamespace"; + static final String DEFAULT_API_NS = "org.onap.dmaap-bc.api"; + static final String BOOT_INSTANCE = "boot"; + private static final String PERM_SEPARATOR = "|"; + private static final String NS_SEPARATOR = "."; + private DmaapConfig dmaapConfig; + private DmaapService dmaapService; + private String instance; + private String apiNamespace; + + public PermissionBuilder(DmaapConfig dmaapConfig, DmaapService dmaapService) { + this.dmaapConfig = dmaapConfig; + this.dmaapService = dmaapService; + initFields(); + } + + public synchronized void updateDmaapInstance() { + if(instance == null || instance.isEmpty() || instance.equalsIgnoreCase(BOOT_INSTANCE)) { + String dmaapName = getDmaapName(); + instance = (dmaapName == null || dmaapName.isEmpty()) ? BOOT_INSTANCE : dmaapName; + } + } + + public String buildPermission(HttpServletRequest httpRequest) { + + StringBuilder sb = new StringBuilder(apiNamespace); + sb.append(NS_SEPARATOR) + .append(getPermissionType(httpRequest.getPathInfo())) + .append(PERM_SEPARATOR) + .append(instance) + .append(PERM_SEPARATOR) + .append(httpRequest.getMethod()); + return sb.toString(); + } + + + private void initFields() { + apiNamespace = dmaapConfig.getProperty(API_NS_PROP, DEFAULT_API_NS); + updateDmaapInstance(); + } + + private String getDmaapName() { + Dmaap dmaap = dmaapService.getDmaap(); + return ( dmaap != null ) ? dmaap.getDmaapName() : BOOT_INSTANCE; + } + + private String getPermissionType(String pathInfo) { + char pathSeparator = '/'; + String relativePath = (pathInfo.charAt(pathInfo.length()-1) == pathSeparator) ? + pathInfo.substring(0,pathInfo.length()-1) : pathInfo; + + String[] pathSlices = relativePath.split(String.valueOf(pathSeparator)); + return pathSlices[pathSlices.length-1]; + } + + String getInstance() { + return instance; + } +} diff --git a/src/main/resources/schema_12.sql b/src/main/resources/schema_12.sql index 7aaab11..c4cef5f 100644 --- a/src/main/resources/schema_12.sql +++ b/src/main/resources/schema_12.sql @@ -7,9 +7,9 @@ -- Licensed under the Apache License, Version 2.0 (the "License"); -- you may not use this file except in compliance with the License. -- You may obtain a copy of the License at --- +-- -- http://www.apache.org/licenses/LICENSE-2.0 --- +-- -- Unless required by applicable law or agreed to in writing, software -- distributed under the License is distributed on an "AS IS" BASIS, -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -21,9 +21,10 @@ @alter table dr_sub - add column guaranteed_delivery boolean, - add column guaranteed_sequence boolean, - add column privileged_subscriber boolean + add column guaranteed_delivery boolean, + add column guaranteed_sequence boolean, + add column privileged_subscriber boolean, + add column decompress boolean ; |