diff options
77 files changed, 4765 insertions, 2171 deletions
@@ -15,6 +15,7 @@ <attributes> <attribute name="optional" value="true"/> <attribute name="maven.pomderived" value="true"/> + <attribute name="test" value="true"/> </attributes> </classpathentry> <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"> @@ -1,5 +1,5 @@ --- -project: 'dmaap-messagerouter-msgrtr' +project: 'dmaap-dbcapi' project_creation_date: '2017-08-29' lifecycle_state: 'Incubation' project_lead: &onap_releng_ptl @@ -9,50 +9,67 @@ project_lead: &onap_releng_ptl company: 'ATT' timezone: 'America/Dallas' primary_contact: *onap_releng_ptl +project_category: '' issue_tracking: type: 'jira' url: 'https://jira.onap.org/projects/DMAAP' key: 'DMAAP' +mailing_list: + type: 'groups.io' + url: 'lists.onap.org' + tag: '<[sub-project_name]>' +realtime_discussion: '' meetings: - type: 'zoom' - agenda: '' - url: 'https://wiki.onap.org/pages/viewpage.action?pageId=13599275' - server: 'n/a' - channel: 'n/a' - repeats: 'weekly' - time: '13:00 UTC' + agenda: '' + url: 'https://wiki.onap.org/pages/viewpage.action?pageId=13599275' + server: 'n/a' + channel: 'n/a' + repeats: 'weekly' + time: '13:00 UTC' +repositories: + - 'dmaap-buscontroller' + - 'dmaap-datarouter' + - 'dmaap-dbcapi' + - 'dmaap-kafka11aaf' + - 'dmaap-messagerouter-dmaapclient' + - 'dmaap-messagerouter-messageservice' + - 'dmaap-messagerouter-mirroragent' + - 'dmaap-messagerouter-msgrtr' + - 'dmaap-oom' + - 'dmaap-zookeeper' committers: - <<: *onap_releng_ptl - name: 'Mandar Sawant' - email: 'ms5838@att.com' - company: 'ATT' - id: 'sawantmandar' - timezone: 'America/Dallas' + email: 'ms5838@att.com' + company: 'ATT' + id: 'sawantmandar' + timezone: 'America/Dallas' - name: 'Varun Gudisena' - email: 'vg411h@att.com' - company: 'ATT' - id: 'vg411h' - timezone: 'America/Dallas' + email: 'vg411h@att.com' + company: 'ATT' + id: 'vg411h' + timezone: 'America/Dallas' - name: 'Bhanu Ramesh' - email: 'bg6954@att.com' - company: 'ATT' - id: 'BhanuRamesh' - timezone: 'America/Dallas' + email: 'bg6954@att.com' + company: 'ATT' + id: 'BhanuRamesh' + timezone: 'America/Dallas' - name: 'Dominic Lunanuova' - email: 'dgl@research.att.com' - company: 'ATT' - id: 'dglFromAtt' - timezone: 'America/Dallas' + email: 'dgl@research.att.com' + company: 'ATT' + id: 'dglFromAtt' + timezone: 'America/Dallas' - name: 'Sunil Unnava' - email: 'su622b@att.com' - company: 'ATT' - id: 'su622b' - timezone: 'America/Louisville' + email: 'su622b@att.com' + company: 'ATT' + id: 'su622b' + timezone: 'America/Louisville' - name: 'Conor Ward' - email: 'conor.ward@ericsson.com' - company: 'ericsson' - id: 'econwar' - timezone: 'America/Dallas' + email: 'conor.ward@ericsson.com' + company: 'ericsson' + id: 'econwar' + timezone: 'America/Dallas' tsc: approval: 'https://lists.onap.org/pipermail/onap-tsc' changes: @@ -98,6 +98,13 @@ The table below lists all the settings, default values (if not set), and shows a |-|-|-|-| |MR.projectID | Value for some constructs of fully qualified topic names | 99999 | ONAP | |-|-|-|-| +|MR.hostnameVerify | Indicates if we want to relax hostname verification on SSL connection | true | false | +|-|-|-|-| +|MR.authentication | Authentication method used when connecting to MR | none | basicAuth | +| | none = no creds sent (default) | | | +| | basicAuth = formulate Basic Auth HTTP Header using name and pwd credentials | | | +| | cert = use client certificate | | | +|-|-|-|-| |cadi.properties | Path to CADI properties file | /opt/app/osaaf/local/org.onap.dmaap-bc.props | /opt/app/osaaf/lcoal/org.onap.dmaap-bc.props | |-|-|-|-| |aaf.URL | URL of the AAF server | https://authentication.domain.netset.com:8095/proxy/ | https://aaf-authz/ | diff --git a/docs/api.rst b/docs/api.rst index 9eab4da..7f187d4 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -4928,3 +4928,54 @@ Topic Model Structure topicName | No | string | | | the short name used by humans, and utilized to construct the `FQTN` version | No | string | | | a hook for any versioning needed for managing a `Topic` over time +Security +~~~~~~~~ +As default security is in Dmaap Bus Controller disabled. + +Enable +------ +Settings to turn on security is in file dmaapbc.properties. The file is located in OOM project in path: ./oom/kubernetes/dmaap/components/dmaap-bc/resources/config/dmaapbc.properties +During deployment the the file is placed into ConfigMap XXX-dmaap-bus-controller-config (XXX depend on deployment setup). The config map is linked to volume with read only permission so it can not be changed from pod level. +Ater updating ConfigMap the bus controller pod needs to be restarted. + +Settings +++++++++ + +In the dmaapbc.properties for security settings there is a main flag: + +1.UseAAF: true + +If set to true then creating topic also will create required perms in AAF. The perms will be created in org.onap.dmaap.mr. +The last element -mr- is related to another setting - MR.projectID . + +Example: + Topic name: + aSimpleTopic + Permitions + org.onap.dmaap.mr.topic|:topic.org.onap.dmaap.mr.aSimpleTopic|pub + org.onap.dmaap.mr.topic|:topic.org.onap.dmaap.mr.aSimpleTopic|sub + org.onap.dmaap.mr.topic|:topic.org.onap.dmaap.mr.aSimpleTopic|view + + +Hint: User defined in the certificate of cadi (property:cadi.properties, user:dmaap-bc@dmaap-bc.onap.org) needs to have permissions to create and view such topics (org.onap.dmaap.mr.topic|*|*). + + +Authentication is using CADI + +CADI confilguration is stored in CADI files. Location of the files is defined in varaible: +cadi.properties: /opt/app/osaaf/local/org.onap.dmaap-bc.props + +The configuration is a mandatory and missing parameter or file cause exception. + +Authorization is done by CADI - configuration is required as above + +Call to bus controller needs to have given user credentials. The user ich checked in AAF for permission to call topic. +The check is done in org.onap.dmaap-bc.api according to ApiNamespace setting. + +Hint: User defined in the certificate of cadi (property:cadi.properties, user:dmaap-bc@dmaap-bc.onap.org) needs to have permission to read the namespace (org.onap.dmaap-bc.api.access|*|read). + + +2.UseAAF: false + +For backward compatibility, if AAF flag is turned off the previous implementation is enabled based on AuthorizationFilter and ApiPermission class. +This filter switching has been made due to the technology differences: Jersey filters do not implement directly servlet API, but CADI filter is based on it.
\ No newline at end of file diff --git a/etc/dmaapbc.properties b/etc/dmaapbc.properties index 64e435e..b0dc7de 100644 --- a/etc/dmaapbc.properties +++ b/etc/dmaapbc.properties @@ -129,7 +129,7 @@ MR.topicStyle: FQTN_LEGACY_FORMAT # MR topic ProjectID MR.projectID: 23456 -MR.multisite: false +MR.multisite: true # # end of MR Related Properties ################################################################################ @@ -347,7 +347,13 @@ <groupId>org.glassfish.jersey.inject</groupId> <artifactId>jersey-hk2</artifactId> </dependency> - </dependencies> + <dependency> + <groupId>pl.pragmatists</groupId> + <artifactId>JUnitParams</artifactId> + <version>1.1.0</version> + <scope>test</scope> + </dependency> + </dependencies> <reporting> <plugins> <plugin> @@ -381,7 +387,7 @@ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <jettyVersion>9.4.12.RC2</jettyVersion> <eelf.version>1.0.0</eelf.version> - <artifact.version>1.0.23-SNAPSHOT</artifact.version> + <artifact.version>1.0.26-SNAPSHOT</artifact.version> <!-- SONAR --> <jacoco.version>0.7.7.201606060606</jacoco.version> <sonar-jacoco-listeners.version>3.2</sonar-jacoco-listeners.version> 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 ; diff --git a/src/test/java/org/onap/dmaap/dbcapi/aaf/AafRoleTest.java b/src/test/java/org/onap/dmaap/dbcapi/aaf/AafRoleTest.java new file mode 100644 index 0000000..c53d8c6 --- /dev/null +++ b/src/test/java/org/onap/dmaap/dbcapi/aaf/AafRoleTest.java @@ -0,0 +1,47 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright 2019 IBM + * ================================================================================ + * 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.aaf; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import org.junit.Before; +import org.junit.Test; + +public class AafRoleTest { + + AafRole aafRole; + + @Before + public void setUp() { + aafRole = new AafRole("testNs", "testRole"); + } + + @Test + public void testAafRole() { + aafRole.setNamespace("namespace"); + aafRole.setRole("role"); + assertEquals("namespace", aafRole.getNamespace()); + assertEquals("role", aafRole.getRole()); + assertEquals("namespace.role", aafRole.getFullyQualifiedRole()); + assertNotNull(aafRole.toJSON()); + } +} diff --git a/src/test/java/org/onap/dmaap/dbcapi/aaf/AafUserRoleTest.java b/src/test/java/org/onap/dmaap/dbcapi/aaf/AafUserRoleTest.java index 6328c21..88fff87 100644 --- a/src/test/java/org/onap/dmaap/dbcapi/aaf/AafUserRoleTest.java +++ b/src/test/java/org/onap/dmaap/dbcapi/aaf/AafUserRoleTest.java @@ -4,6 +4,8 @@ * ================================================================================ * Copyright (C) 2019 IBM 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. * You may obtain a copy of the License at @@ -20,16 +22,37 @@ package org.onap.dmaap.dbcapi.aaf; -import org.junit.Test; - import static org.hamcrest.CoreMatchers.is; -import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThat; + +import org.junit.Before; +import org.junit.Test; public class AafUserRoleTest { + AafUserRole aafUserRole; + + @Before + public void setUp() { + aafUserRole = new AafUserRole("xyz", "admin"); + } + + @Test + public void testGetIdentity() { + aafUserRole.setIdentity("xyz"); + assertEquals("xyz", aafUserRole.getIdentity()); + } + + @Test + public void testGetRole() { + aafUserRole.setRole("admin"); + assertEquals("admin", aafUserRole.getRole()); + } + @Test public void toJSON() { - AafUserRole role = new AafUserRole("test","admin"); + AafUserRole role = new AafUserRole("test", "admin"); assertThat(role.toJSON(), is(" { \"user\": \"test\", \"role\": \"admin\" }")); } }
\ No newline at end of file diff --git a/src/test/java/org/onap/dmaap/dbcapi/database/DBFieldHandlerTest.java b/src/test/java/org/onap/dmaap/dbcapi/database/DBFieldHandlerTest.java index c1e9c35..5171aaa 100644 --- a/src/test/java/org/onap/dmaap/dbcapi/database/DBFieldHandlerTest.java +++ b/src/test/java/org/onap/dmaap/dbcapi/database/DBFieldHandlerTest.java @@ -1,10 +1,11 @@ - /*- * ============LICENSE_START======================================================= * org.onap.dmaap * ================================================================================ * Copyright (C) 2018 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. * You may obtain a copy of the License at @@ -18,32 +19,36 @@ * limitations under the License. * ============LICENSE_END========================================================= */ + package org.onap.dmaap.dbcapi.database; -import org.onap.dmaap.dbcapi.database.DBFieldHandler; -import org.onap.dmaap.dbcapi.model.*; -import org.onap.dmaap.dbcapi.testframework.ReflectionHarness; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; -import static org.junit.Assert.*; +import java.sql.PreparedStatement; +import java.sql.ResultSet; -import org.junit.After; -import org.junit.Before; +import org.apache.log4j.Logger; import org.junit.Test; -import java.util.*; -import java.sql.*; +import org.onap.dmaap.dbcapi.authentication.AafLurAndFish; +import org.onap.dmaap.dbcapi.model.ReplicationType; +import org.onap.dmaap.dbcapi.testframework.ReflectionHarness; public class DBFieldHandlerTest { - private static final String fmt = "%24s: %s%n"; + private static final Logger logger = Logger.getLogger(AafLurAndFish.class); - ReflectionHarness rh = new ReflectionHarness(); + private static final String fmt = "%24s: %s%n"; - private static class TopicReplicationTypeHandler implements DBFieldHandler.SqlOp { + ReflectionHarness rh = new ReflectionHarness(); + + 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); @@ -55,53 +60,55 @@ public class DBFieldHandlerTest { } } + @Test + public void test1() { + // rh.reflect( "org.onap.dmaap.dbcapi.aaf.client.MrTopicConnection", "get", + // "idNotSet@namespaceNotSet:pwdNotSet" ); + } + @Test + public void test2() { + String v = "Validate"; + // rh.reflect( "org.onap.dmaap.dbcapi.aaf.client.MrTopicConnection", "set", v ); + } - @Before - public void setUp() throws Exception { - } - - @After - public void tearDown() throws Exception { - } - - - @Test - public void test1() { - - - //rh.reflect( "org.onap.dmaap.dbcapi.aaf.client.MrTopicConnection", "get", "idNotSet@namespaceNotSet:pwdNotSet" ); - - } - - @Test - public void test2() { - String v = "Validate"; - //rh.reflect( "org.onap.dmaap.dbcapi.aaf.client.MrTopicConnection", "set", v ); - - } - - @Test - public void test3() { - - try { - DBFieldHandler fh = new DBFieldHandler( String.class, "aString", 1 ); - } catch (Exception e ) { - } - - } - - @Test - public void test4() { - - try { - DBFieldHandler fh = new DBFieldHandler( String.class, "aString", 1, null ); - } catch (Exception e ) { - } + @Test + public void test3() { + try { + DBFieldHandler fh = new DBFieldHandler(String.class, "aString", 1); + } catch (Exception e) { + logger.error("Error", e); + } + } - } + @Test + public void test4() { + try { + DBFieldHandler fh = new DBFieldHandler(String.class, "aString", 1, null); + } catch (Exception e) { + logger.error("Error", e); + } + } + @Test + public void testfesc() { + String sampleString = "@xyz,ww;,"; + String finalString = DBFieldHandler.fesc(sampleString); + assertEquals("@axyz@cww@s@c", finalString); + } + @Test + public void testfunesc() { + String sampleString = "@axyz@cww@s@c"; + String convertedString = DBFieldHandler.funesc(sampleString); + assertEquals("@xyz,ww;,", convertedString); + } + @Test + public void testfescWithNull() { + String sampleString1 = DBFieldHandler.fesc(null); + String sampleString2 = DBFieldHandler.funesc(null); + assertNull(null, sampleString1); + assertNull(null, sampleString2); + } } - diff --git a/src/test/java/org/onap/dmaap/dbcapi/database/TableHandlerTest.java b/src/test/java/org/onap/dmaap/dbcapi/database/TableHandlerTest.java index dc2bb2f..af44db0 100644 --- a/src/test/java/org/onap/dmaap/dbcapi/database/TableHandlerTest.java +++ b/src/test/java/org/onap/dmaap/dbcapi/database/TableHandlerTest.java @@ -71,7 +71,7 @@ public class TableHandlerTest { public void test1() { - //rh.reflect( "org.onap.dmaap.dbcapi.aaf.client.MrTopicConnection", "get", "idNotSet@namespaceNotSet:pwdNotSet" ); + rh.reflect( "org.onap.dmaap.dbcapi.aaf.client.MrTopicConnection", "get", "idNotSet@namespaceNotSet:pwdNotSet" ); } @@ -84,17 +84,21 @@ public class TableHandlerTest { @Test public void test3() { - TableHandler.setSpecialCase("topic", "replication_case", new TopicReplicationTypeHandler()); + DBFieldHandler.SqlOp trth = new TopicReplicationTypeHandler(); + TableHandler.setSpecialCase("topic", "replication_case", trth); try { ConnectionFactory cf = new ConnectionFactory(); TableHandler th = new TableHandler( cf, TopicReplicationTypeHandler.class, "foo", "bar" ); + DBFieldHandler.SqlOp t = th.getSpecialCase( "foo", "bar" ); + assert( trth == t ); } catch (Exception e ) { } try { - ConnectionFactory cf = new ConnectionFactory(); + TableHandler th = new TableHandler( TopicReplicationTypeHandler.class, "foo", "bar" ); - th.getSpecialCase( "foo", "bar" ); + DBFieldHandler.SqlOp t = th.getSpecialCase( "foo", "bar" ); + assert( trth == t ); } catch (Exception e ) { } diff --git a/src/test/java/org/onap/dmaap/dbcapi/model/BrTopicTest.java b/src/test/java/org/onap/dmaap/dbcapi/model/BrTopicTest.java new file mode 100644 index 0000000..11e7c85 --- /dev/null +++ b/src/test/java/org/onap/dmaap/dbcapi/model/BrTopicTest.java @@ -0,0 +1,59 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright 2019 IBM + * ================================================================================ + * 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.model; + +import static org.junit.Assert.assertEquals; + +import org.junit.Before; +import org.junit.Test; + +public class BrTopicTest { + + BrTopic brTopic; + + @Before + public void setUp() { + brTopic = new BrTopic(); + } + + @Test + public void testGetBrSource() { + brTopic.setBrSource("brSource"); + assertEquals("brSource", brTopic.getBrSource()); + } + + @Test + public void testGetBrTarget() { + brTopic.setBrTarget("brTarget"); + assertEquals("brTarget", brTopic.getBrTarget()); + } + + @Test + public void testGetTopicCount() { + brTopic.setTopicCount(1); + assertEquals(1, brTopic.getTopicCount()); + } + + @Test + public void testGetMmAgentName() { + brTopic.setMmAgentName("Test"); + assertEquals("Test", brTopic.getMmAgentName()); + } +} diff --git a/src/test/java/org/onap/dmaap/dbcapi/model/DRSubTest.java b/src/test/java/org/onap/dmaap/dbcapi/model/DRSubTest.java index 480ff07..95cf9c9 100644 --- a/src/test/java/org/onap/dmaap/dbcapi/model/DRSubTest.java +++ b/src/test/java/org/onap/dmaap/dbcapi/model/DRSubTest.java @@ -69,7 +69,7 @@ public class DRSubTest { assertTrue( t.isGuaranteedDelivery() == false ); assertTrue( t.isGuaranteedSequence() == false ); assertTrue( t.isPrivilegedSubscriber() == false ); - + assertTrue( t.isDecompress() == false ); } @Test @@ -113,6 +113,8 @@ public class DRSubTest { assertTrue( t.isGuaranteedSequence() == v ); t.setPrivilegedSubscriber(v); assertTrue( t.isPrivilegedSubscriber() == v ); + t.setDecompress(v); + assertTrue( t.isDecompress() == v ); } @Test diff --git a/src/test/java/org/onap/dmaap/dbcapi/model/DmaapTest.java b/src/test/java/org/onap/dmaap/dbcapi/model/DmaapTest.java index fb83fe9..c0f3bef 100644 --- a/src/test/java/org/onap/dmaap/dbcapi/model/DmaapTest.java +++ b/src/test/java/org/onap/dmaap/dbcapi/model/DmaapTest.java @@ -19,17 +19,14 @@ */ package org.onap.dmaap.dbcapi.model; -import static org.junit.Assert.*; - -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; +import static org.junit.Assert.assertTrue; import org.junit.After; import org.junit.Before; import org.junit.Test; + public class DmaapTest { - String ver, tnr, dn, dpu, lu, bat, nk, ako; + private String ver, tnr, dn, dpu, lu, bat, nk, ako; @Before public void setUp() throws Exception { diff --git a/src/test/java/org/onap/dmaap/dbcapi/model/MRClientTest.java b/src/test/java/org/onap/dmaap/dbcapi/model/MRClientTest.java index 15753cd..ba95a85 100644 --- a/src/test/java/org/onap/dmaap/dbcapi/model/MRClientTest.java +++ b/src/test/java/org/onap/dmaap/dbcapi/model/MRClientTest.java @@ -4,6 +4,8 @@ * ================================================================================ * Copyright (C) 2018 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. * You may obtain a copy of the License at @@ -17,6 +19,7 @@ * limitations under the License. * ============LICENSE_END========================================================= */ + package org.onap.dmaap.dbcapi.model; import static org.junit.Assert.*; @@ -26,67 +29,83 @@ import org.junit.Before; import org.junit.Test; import org.onap.dmaap.dbcapi.testframework.ReflectionHarness; - public class MRClientTest { - private static final String fmt = "%24s: %s%n"; - - ReflectionHarness rh = new ReflectionHarness(); - - String d, t, f, c, m; - - @Before - public void setUp() throws Exception { - d = "central-onap"; - t = "org.onap.dmaap.interestingTopic"; - f = "mrc.onap.org:3904/events/org.onap.dmaap.interestingTopic"; - c = "publisher"; - m = "m12345"; - } - - @After - public void tearDown() throws Exception { - } - - - @Test - public void test1() { - - // can't use simple reflection to test for null since null constructor initializes some fields. - //rh.reflect( "org.onap.dmaap.dbcapi.model.MR_Client", "get", null ); - // so brute force instead... - String[] a = { "put", "view" }; - MR_Client m = new MR_Client(); - - - assertTrue( null == m.getDcaeLocationName() ); - assertTrue( null == m.getFqtn() ); - assertTrue( null == m.getClientRole() ); - assertTrue( null == m.getAction() ); - - } - - @Test - public void test2() { - String[] a = { "put", "view" }; - MR_Client m = new MR_Client( d, f, c, a ); - - - assertTrue( d.equals( m.getDcaeLocationName() )); - assertTrue( f.equals( m.getFqtn() )); - assertTrue( c.equals( m.getClientRole() )); - String[] ma = m.getAction(); - assertTrue( a.length == ma.length ); - for( int i = 0; i < a.length; i++ ) { - assertTrue( a[i].equals( ma[i] ) ); - } - } - - @Test - public void test3() { - - String v = "Validate"; - rh.reflect( "org.onap.dmaap.dbcapi.model.MR_Client", "set", v ); - } + private static final String fmt = "%24s: %s%n"; + + ReflectionHarness rh = new ReflectionHarness(); + + String d, t, f, c, m; + + @Before + public void setUp() throws Exception { + d = "central-onap"; + t = "org.onap.dmaap.interestingTopic"; + f = "mrc.onap.org:3904/events/org.onap.dmaap.interestingTopic"; + c = "publisher"; + m = "m12345"; + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void test1() { + + // can't use simple reflection to test for null since null constructor + // initializes some fields. + // rh.reflect( "org.onap.dmaap.dbcapi.model.MR_Client", "get", null ); + // so brute force instead... + String[] a = { "put", "view" }; + MR_Client m = new MR_Client(); + + assertTrue(null == m.getDcaeLocationName()); + assertTrue(null == m.getFqtn()); + assertTrue(null == m.getClientRole()); + assertTrue(null == m.getAction()); + + } + + @Test + public void test2() { + String[] a = { "put", "view" }; + MR_Client m = new MR_Client(d, f, c, a); + + assertTrue(d.equals(m.getDcaeLocationName())); + assertTrue(f.equals(m.getFqtn())); + assertTrue(c.equals(m.getClientRole())); + String[] ma = m.getAction(); + assertTrue(a.length == ma.length); + for (int i = 0; i < a.length; i++) { + assertTrue(a[i].equals(ma[i])); + } + } + + @Test + public void test3() { + + String v = "Validate"; + rh.reflect("org.onap.dmaap.dbcapi.model.MR_Client", "set", v); + } + + @Test + public void test4() { + MR_Client mrClient = new MR_Client(); + String stringArray[] = { "test" }; + mrClient.setAction(stringArray); + mrClient.hasAction(""); + mrClient.setMrClientId("mrClientId"); + mrClient.setTopicURL("testTopicURL"); + mrClient.setClientIdentity("clientIdentity"); + + assertEquals("clientIdentity", mrClient.getClientIdentity()); + assertEquals("testTopicURL", mrClient.getTopicURL()); + assertEquals("mrClientId", mrClient.getMrClientId()); + assertEquals(false, mrClient.isPublisher()); + assertEquals(false, mrClient.isSubscriber()); + assertEquals("test", mrClient.getAction()[0]); + + } } diff --git a/src/test/java/org/onap/dmaap/dbcapi/model/MR_ClusterTest.java b/src/test/java/org/onap/dmaap/dbcapi/model/MR_ClusterTest.java index ebe7b1e..514e0d1 100644 --- a/src/test/java/org/onap/dmaap/dbcapi/model/MR_ClusterTest.java +++ b/src/test/java/org/onap/dmaap/dbcapi/model/MR_ClusterTest.java @@ -30,7 +30,7 @@ import org.junit.Before; import org.junit.Test; import org.onap.dmaap.dbcapi.testframework.ReflectionHarness; public class MR_ClusterTest { - String d, fqdn; + String d, fqdn, repGrp, p1, p2, prot, p0; ReflectionHarness rh = new ReflectionHarness(); @@ -38,6 +38,14 @@ public class MR_ClusterTest { public void setUp() throws Exception { d = "central-onap"; fqdn = "mr.onap.org"; + repGrp = "zeppelin"; + prot = "http"; + p0 = "3904"; + p1 = "9092"; + p2 = "2323"; + + + } @After @@ -58,10 +66,45 @@ public class MR_ClusterTest { @Test public void testMR_ClusterClassConstructor() { - MR_Cluster t = new MR_Cluster( d, fqdn, "http", "3904"); + MR_Cluster t = new MR_Cluster( d, fqdn, prot, p0); + + assertTrue( t.getDcaeLocationName() == d ); + assertTrue( t.getFqdn() == fqdn ); + assertTrue( t.getTopicProtocol() == prot ); + assertTrue( t.getTopicPort() == p0 ); + + // pass null params to trigger default settings + t = new MR_Cluster( d, fqdn, null, null ); + + assertTrue( t.getDcaeLocationName() == d ); + assertTrue( t.getFqdn() == fqdn ); + assertTrue( t.getTopicProtocol() != null ); + assertTrue( t.getTopicPort() != null ); + } + + @Test + public void testMR_ClusterManyArgsClassConstructor() { + + MR_Cluster t = new MR_Cluster( d, fqdn, prot, p0, repGrp, p1, p2 ); assertTrue( t.getDcaeLocationName() == d ); assertTrue( t.getFqdn() == fqdn ); + assertTrue( t.getTopicProtocol() == prot ); + assertTrue( t.getTopicPort() == p0 ); + assertTrue( t.getReplicationGroup() == repGrp ); + assertTrue( t.getSourceReplicationPort() == p1 ); + assertTrue( t.getTargetReplicationPort() == p2 ); + + // pass null params to trigger default settings + t = new MR_Cluster( d, fqdn, null, null, null, null, null ); + + assertTrue( t.getDcaeLocationName() == d ); + assertTrue( t.getFqdn() == fqdn ); + assertTrue( t.getTopicProtocol() != null ); + assertTrue( t.getTopicPort() != null ); + assertTrue( t.getReplicationGroup() != null ); + assertTrue( t.getSourceReplicationPort() != null ); + assertTrue( t.getTargetReplicationPort() != null ); } @Test @@ -72,7 +115,13 @@ public class MR_ClusterTest { assertTrue( t.getDcaeLocationName() == null ); assertTrue( t.getFqdn() == null ); - String fqtn = t.genTopicURL( "cluster2.onap.org", "org.onap.topic2" ); + String override = "cluster2.onap.org"; + String topic2 = "org.onap.topic2"; + String fqtn = t.genTopicURL( override, topic2 ); + assertTrue( fqtn.contains( override) && fqtn.contains(topic2)); + + fqtn = t.genTopicURL( null, "org.onap.topic2" ); + assertTrue(fqtn.contains(topic2)); } diff --git a/src/test/java/org/onap/dmaap/dbcapi/model/TopicTest.java b/src/test/java/org/onap/dmaap/dbcapi/model/TopicTest.java index 5180b99..5da3aed 100644 --- a/src/test/java/org/onap/dmaap/dbcapi/model/TopicTest.java +++ b/src/test/java/org/onap/dmaap/dbcapi/model/TopicTest.java @@ -4,6 +4,8 @@ * ================================================================================ * Copyright (C) 2018 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. * You may obtain a copy of the License at @@ -19,62 +21,67 @@ */ package org.onap.dmaap.dbcapi.model; -import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; import org.junit.After; import org.junit.Before; import org.junit.Test; +import org.onap.dmaap.dbcapi.model.DmaapObject.DmaapObject_Status; import org.onap.dmaap.dbcapi.testframework.ReflectionHarness; - public class TopicTest { - private static final String fmt = "%24s: %s%n"; - - ReflectionHarness rh = new ReflectionHarness(); - - String f, t, d, e, o; - - @Before - public void setUp() throws Exception { - f = "org.onap.dmaap.interestingTopic"; - t = "interestingTopic"; - d = "A so very interesting topic"; - e = "Yes"; - o = "m12345"; - } - - @After - public void tearDown() throws Exception { - } - - - @Test - public void test1() { - - - rh.reflect( "org.onap.dmaap.dbcapi.model.Topic", "get", null ); - - } - - @Test - public void test2() { - String[] a = { "put", "view" }; - Topic obj = new Topic( f, t, d, e, o ); - - - assertTrue( f.equals( obj.getFqtn() )); - assertTrue( t.equals( obj.getTopicName() )); - assertTrue( d.equals( obj.getTopicDescription() )); - assertTrue( e.equals( obj.getTnxEnabled() )); - assertTrue( o.equals( obj.getOwner() )); - } - - @Test - public void test3() { - - String v = "Validate"; - rh.reflect( "org.onap.dmaap.dbcapi.model.Topic", "set", v ); - } + ReflectionHarness rh = new ReflectionHarness(); + + String f, t, d, e, o; + + @Before + public void setUp() throws Exception { + f = "org.onap.dmaap.interestingTopic"; + t = "interestingTopic"; + d = "A so very interesting topic"; + e = "Yes"; + o = "m12345"; + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void test1() { + rh.reflect("org.onap.dmaap.dbcapi.model.Topic", "get", null); + } + + @Test + public void test2() { + Topic obj = new Topic(f, t, d, e, o); + assertTrue(f.equals(obj.getFqtn())); + assertTrue(t.equals(obj.getTopicName())); + assertTrue(d.equals(obj.getTopicDescription())); + assertTrue(e.equals(obj.getTnxEnabled())); + assertTrue(o.equals(obj.getOwner())); + } + + @Test + public void test3() { + String v = "Validate"; + rh.reflect("org.onap.dmaap.dbcapi.model.Topic", "set", v); + } + + @Test + public void getNumClientsHavingMRClientListNull() { + Topic obj = new Topic(f, t, d, e, o); + obj.setClients(null); + assertEquals(0, obj.getNumClients()); + } + + @Test + public void testTopicInitializationWithInvalidJsonString() { + String json = "{\"key\":\"value\""; + Topic obj = new Topic(json); + assertEquals(DmaapObject_Status.INVALID, obj.getStatus()); + } } diff --git a/src/test/java/org/onap/dmaap/dbcapi/resources/AAFAuthenticationFilterTest.java b/src/test/java/org/onap/dmaap/dbcapi/resources/AAFAuthenticationFilterTest.java new file mode 100644 index 0000000..d5ae5fd --- /dev/null +++ b/src/test/java/org/onap/dmaap/dbcapi/resources/AAFAuthenticationFilterTest.java @@ -0,0 +1,178 @@ +/*- + * ============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 static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.mockito.Matchers.anyString; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.Mockito.verifyZeroInteractions; + +import java.io.PrintWriter; +import java.io.StringWriter; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.Spy; +import org.mockito.runners.MockitoJUnitRunner; +import org.onap.aaf.cadi.filter.CadiFilter; +import org.onap.dmaap.dbcapi.util.DmaapConfig; + +@RunWith(MockitoJUnitRunner.class) +public class AAFAuthenticationFilterTest { + + @Spy + private AAFAuthenticationFilter filter; + @Mock + private FilterConfig filterConfig; + @Mock + private CadiFilter cadiFilterMock; + @Mock + private HttpServletRequest servletRequest; + @Mock + private HttpServletResponse servletResponse; + @Mock + private FilterChain filterChain; + @Mock + private DmaapConfig dmaapConfig; + + @Rule + public ExpectedException thrown = ExpectedException.none(); + + @Before + public void setUp() throws Exception { + doReturn(dmaapConfig).when(filter).getConfig(); + } + + @Test + public void init_shouldNotInitializeCADI_whenAafIsNotUsed() throws Exception { + //given + doReturn("false").when(dmaapConfig).getProperty(eq(AAFAuthenticationFilter.AAF_AUTHN_FLAG), anyString()); + + //when + filter.init(filterConfig); + + //then + assertFalse(filter.isAafEnabled()); + assertNull(filter.getCadiFilter()); + } + + @Test + public void doFilter_shouldSkipCADI_whenAafIsNotUsed() throws Exception { + //given + doReturn("false").when(dmaapConfig).getProperty(eq(AAFAuthenticationFilter.AAF_AUTHN_FLAG), anyString()); + filter.init(filterConfig); + filter.setCadiFilter(cadiFilterMock); + + //when + filter.doFilter(servletRequest, servletResponse, filterChain); + + //then + verify(filterChain).doFilter(servletRequest,servletResponse); + verifyZeroInteractions(cadiFilterMock,servletRequest,servletResponse); + } + + @Test + public void init_shouldFail_whenAafIsUsed_andCadiPropertiesHasNotBeenSet() throws Exception { + //given + doReturn("true").when(dmaapConfig).getProperty(eq(AAFAuthenticationFilter.AAF_AUTHN_FLAG), anyString()); + doReturn("").when(dmaapConfig).getProperty(AAFAuthenticationFilter.CADI_PROPERTIES); + + //then + thrown.expect(ServletException.class); + thrown.expectMessage("Cannot initialize CADI filter.CADI properties not available."); + + //when + filter.init(filterConfig); + } + + @Test + public void init_shouldInitializeCADI_whenAafIsUsed_andCadiPropertiesSet() throws Exception { + //given + doReturn("true").when(dmaapConfig).getProperty(eq(AAFAuthenticationFilter.AAF_AUTHN_FLAG), anyString()); + doReturn("cadi.properties").when(dmaapConfig).getProperty(AAFAuthenticationFilter.CADI_PROPERTIES); + + //when + filter.init(filterConfig); + + //then + assertTrue(filter.isAafEnabled()); + assertNotNull(filter.getCadiFilter()); + } + + @Test + public void doFilter_shouldUseCADIfilter_andAuthenticateUser_whenAAFisUsed_andUserIsValid() throws Exception{ + //given + initCADIFilter(); + doReturn(200).when(servletResponse).getStatus(); + + //when + filter.doFilter(servletRequest,servletResponse,filterChain); + + //then + verify(cadiFilterMock).doFilter(servletRequest,servletResponse,filterChain); + verify(servletResponse).getStatus(); + verifyNoMoreInteractions(servletResponse); + verifyZeroInteractions(filterChain, servletRequest); + } + + @Test + public void doFilter_shouldUseCADIfilter_andReturnAuthenticationError_whenAAFisUsed_andUserInvalid() throws Exception{ + //given + String errorResponseJson = "{\"code\":401,\"message\":\"invalid or no credentials provided\",\"fields\":\"Authentication\",\"2xx\":false}"; + initCADIFilter(); + doReturn(401).when(servletResponse).getStatus(); + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + doReturn(pw).when(servletResponse).getWriter(); + + //when + filter.doFilter(servletRequest,servletResponse,filterChain); + + //then + verify(cadiFilterMock).doFilter(servletRequest,servletResponse,filterChain); + verify(servletResponse).getStatus(); + verify(servletResponse).setContentType("application/json"); + verifyZeroInteractions(filterChain, servletRequest); + assertEquals(errorResponseJson, sw.toString()); + } + + private void initCADIFilter() throws Exception{ + doReturn("true").when(dmaapConfig).getProperty(eq(AAFAuthenticationFilter.AAF_AUTHN_FLAG), anyString()); + doReturn("cadi.properties").when(dmaapConfig).getProperty(AAFAuthenticationFilter.CADI_PROPERTIES); + filter.init(filterConfig); + filter.setCadiFilter(cadiFilterMock); + } + +}
\ No newline at end of file diff --git a/src/test/java/org/onap/dmaap/dbcapi/resources/AAFAuthorizationFilterTest.java b/src/test/java/org/onap/dmaap/dbcapi/resources/AAFAuthorizationFilterTest.java new file mode 100644 index 0000000..73794cd --- /dev/null +++ b/src/test/java/org/onap/dmaap/dbcapi/resources/AAFAuthorizationFilterTest.java @@ -0,0 +1,172 @@ +/*- + * ============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 static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.mockito.Matchers.anyString; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.Mockito.verifyZeroInteractions; +import static org.mockito.Mockito.when; + +import java.io.PrintWriter; +import java.io.StringWriter; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.Spy; +import org.mockito.runners.MockitoJUnitRunner; +import org.onap.dmaap.dbcapi.model.Dmaap; +import org.onap.dmaap.dbcapi.service.DmaapService; +import org.onap.dmaap.dbcapi.util.DmaapConfig; +import org.onap.dmaap.dbcapi.util.PermissionBuilder; +import sun.security.acl.PrincipalImpl; + +@RunWith(MockitoJUnitRunner.class) +public class AAFAuthorizationFilterTest { + + @Spy + private AAFAuthorizationFilter filter; + @Mock + private FilterConfig filterConfig; + @Mock + private HttpServletRequest servletRequest; + @Mock + private HttpServletResponse servletResponse; + @Mock + private FilterChain filterChain; + @Mock + private DmaapConfig dmaapConfig; + @Mock + private PermissionBuilder permissionBuilder; + @Mock + private DmaapService dmaapService; + + @Before + public void setUp() throws Exception { + filter.setPermissionBuilder(permissionBuilder); + doReturn(dmaapConfig).when(filter).getConfig(); + doReturn(dmaapService).when(filter).getDmaapService(); + } + + @Test + public void init_shouldNotInitializePermissionBuilder_whenAAFnotUsed() throws Exception { + //given + filter.setPermissionBuilder(null); + configureAAFUsage(false); + + //when + filter.init(filterConfig); + + //then + assertNull(filter.getPermissionBuilder()); + } + + @Test + public void init_shouldInitializePermissionBuilder_whenAAFisUsed() throws Exception { + //given + filter.setPermissionBuilder(null); + configureAAFUsage(true); + //doReturn(provideEmptyInstance()).when(dmaapService).getDmaap(); + when(dmaapService.getDmaap()).thenReturn(mock(Dmaap.class)); + + //when + filter.init(filterConfig); + + //then + assertNotNull(permissionBuilder); + } + + @Test + public void doFilter_shouldSkipAuthorization_whenAAFnotUsed() throws Exception { + //given + filter.setAafEnabled(false); + + //when + filter.doFilter(servletRequest,servletResponse,filterChain); + + //then + verify(filterChain).doFilter(servletRequest,servletResponse); + verifyNoMoreInteractions(filterChain); + verifyZeroInteractions(permissionBuilder, servletRequest, servletResponse); + } + + @Test + public void doFilter_shouldPass_whenUserHasPermissionToResourceEndpoint() throws Exception { + //given + String user = "johnny"; + String permission = "org.onap.dmaap-bc.api.topics|mr|GET"; + when(permissionBuilder.buildPermission(servletRequest)).thenReturn(permission); + configureServletRequest(permission, user, true); + filter.setAafEnabled(true); + + //when + filter.doFilter(servletRequest,servletResponse,filterChain); + + //then + verify(filterChain).doFilter(servletRequest,servletResponse); + verify(permissionBuilder).updateDmaapInstance(); + verifyZeroInteractions(servletResponse); + } + + @Test + public void doFilter_shouldReturnError_whenUserDontHavePermissionToResourceEndpoint() throws Exception { + //given + String user = "jack"; + String permission = "org.onap.dmaap-bc.api.topics|mr|GET"; + when(permissionBuilder.buildPermission(servletRequest)).thenReturn(permission); + configureServletRequest(permission, user, false); + filter.setAafEnabled(true); + + String errorMsgJson = "{\"code\":403,\"message\":\"User "+user+" does not have permission " + + permission +"\",\"fields\":\"Authorization\",\"2xx\":false}"; + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + when(servletResponse.getWriter()).thenReturn(pw); + + //when + filter.doFilter(servletRequest,servletResponse,filterChain); + + //then + verifyZeroInteractions(filterChain); + verify(permissionBuilder).updateDmaapInstance(); + verify(servletResponse).setStatus(403); + assertEquals(errorMsgJson, sw.toString()); + } + + private void configureServletRequest(String permission, String user, boolean isUserInRole) { + when(servletRequest.getUserPrincipal()).thenReturn(new PrincipalImpl(user)); + when(servletRequest.isUserInRole(permission)).thenReturn(isUserInRole); + } + + private void configureAAFUsage(Boolean isUsed) { + doReturn(isUsed.toString()).when(dmaapConfig).getProperty(eq(AAFAuthorizationFilter.AAF_AUTHZ_FLAG), anyString()); + } +}
\ No newline at end of file diff --git a/src/test/java/org/onap/dmaap/dbcapi/resources/DR_NodeResourceTest.java b/src/test/java/org/onap/dmaap/dbcapi/resources/DR_NodeResourceTest.java index 01ef6ae..856a789 100644 --- a/src/test/java/org/onap/dmaap/dbcapi/resources/DR_NodeResourceTest.java +++ b/src/test/java/org/onap/dmaap/dbcapi/resources/DR_NodeResourceTest.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. @@ -19,107 +19,231 @@ */ package org.onap.dmaap.dbcapi.resources; -import org.onap.dmaap.dbcapi.model.*; -import org.onap.dmaap.dbcapi.service.*; -import org.onap.dmaap.dbcapi.testframework.DmaapObjectFactory; - -import static org.junit.Assert.*; - -import org.junit.After; +import org.glassfish.jersey.server.ResourceConfig; +import org.junit.AfterClass; import org.junit.Before; +import org.junit.BeforeClass; import org.junit.Test; -import java.util.*; -import java.sql.*; +import org.onap.dmaap.dbcapi.database.DatabaseClass; +import org.onap.dmaap.dbcapi.model.ApiError; +import org.onap.dmaap.dbcapi.model.DR_Node; +import org.onap.dmaap.dbcapi.testframework.DmaapObjectFactory; -import org.glassfish.jersey.test.JerseyTest; -import org.glassfish.jersey.server.ResourceConfig; import javax.ws.rs.client.Entity; -import javax.ws.rs.core.Application; import javax.ws.rs.core.Response; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.Path; -import javax.ws.rs.GET; - - -public class DR_NodeResourceTest extends JerseyTest { - - static DmaapObjectFactory factory = new DmaapObjectFactory(); - static String entry_path = "dr_nodes"; - - @Override - protected Application configure() { - return new ResourceConfig( DR_NodeResource.class ); - } - - private static final String fmt = "%24s: %s%n"; - - - -/* may conflict with test framework! - @Before - public void preTest() throws Exception { - } - - @After - public void tearDown() throws Exception { - } -*/ - - - @Test - public void GetTest() { - Response resp = target( entry_path ).request().get( Response.class ); - System.out.println( "GET " + entry_path + " resp=" + resp.getStatus() ); - - assertTrue( resp.getStatus() == 200 ); - } - @Test - public void PostTest() { - DR_Node node = factory.genDR_Node( "central" ); - Entity<DR_Node> reqEntity = Entity.entity( node, MediaType.APPLICATION_JSON ); - Response resp = target( entry_path ).request().post( reqEntity, Response.class ); - System.out.println( "POST " + entry_path + " resp=" + resp.getStatus() + " " + resp.readEntity( String.class ) ); - assertTrue( resp.getStatus() == 200 ); - } - - @Test - public void PutTest() { - -/* - try { - DcaeLocation loc = factory.genDcaeLocation( "central" ); - Entity<DcaeLocation> reqEntity = Entity.entity( loc, MediaType.APPLICATION_JSON ); - Response resp = target( "dcaeLocations").request().post( reqEntity, Response.class ); - System.out.println( "POST dcaeLocation resp=" + resp.getStatus() + " " + resp.readEntity( String.class )); - assertTrue( resp.getStatus() == 201 ); - } catch (Exception e ) { - } -*/ - - DR_Node node = factory.genDR_Node( "central" ); - Entity<DR_Node> reqEntity = Entity.entity( node, MediaType.APPLICATION_JSON ); - Response resp = target( entry_path ).request().post( reqEntity, Response.class ); - - // first, add it - System.out.println( "POST " + entry_path + " resp=" + resp.getStatus() + " " + resp.readEntity( String.class ) ); - assertTrue( resp.getStatus() == 200 ); - - // now change a field - node.setVersion( "1.0.2" ); - reqEntity = Entity.entity( node, MediaType.APPLICATION_JSON ); - - // update currently fails... - resp = target( entry_path ) - .path( node.getFqdn()) - .request() - .put( reqEntity, Response.class ); - System.out.println( "PUT " + entry_path + "/" + node.getFqdn() + " resp=" + resp.getStatus() + " " + resp.readEntity(String.class)); - assertTrue( resp.getStatus() == 404 ); - - } - - +import static javax.ws.rs.client.Entity.entity; +import static javax.ws.rs.core.MediaType.APPLICATION_JSON; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + + +public class DR_NodeResourceTest { + + private static final DmaapObjectFactory DMAAP_OBJECT_FACTORY = new DmaapObjectFactory(); + private static FastJerseyTestContainer testContainer; + + @BeforeClass + public static void setUpClass() throws Exception { + DatabaseClass.getDmaap().init(DMAAP_OBJECT_FACTORY.genDmaap()); + + testContainer = new FastJerseyTestContainer(new ResourceConfig() + .register(DR_NodeResource.class)); + testContainer.init(); + } + + @AfterClass + public static void tearDownClass() throws Exception { + testContainer.destroy(); + /*TODO: Cannot cleanup yet until still other Resources tests depends on the static DB content + + DatabaseClass.clearDatabase(); + DatabaseClass.getDmaap().remove();*/ + } + + @Test + public void getDr_Nodes_test() { + Response response = testContainer.target("dr_nodes").request().get(Response.class); + System.out.println("GET dr_subs response=" + response.getStatus()); + + assertEquals(200, response.getStatus()); + assertTrue(response.hasEntity()); + } + + @Test + public void addDr_Node_shouldReturnError_whenNoLocationAndFqdnProvided() { + DR_Node node = new DR_Node(null, null, "hostName", "1.0"); + Entity<DR_Node> requestedEntity = entity(node, APPLICATION_JSON); + + Response response = testContainer.target("dr_nodes") + .request() + .post(requestedEntity, Response.class); + + assertEquals(400, response.getStatus()); + ApiError responseError = response.readEntity(ApiError.class); + assertNotNull(responseError); + assertEquals("dcaeLocation, fqdn", responseError.getFields()); + } + + @Test + public void addDr_Node_shouldReturnError_whenDrNodeWithGiveFqdnAlreadyExists() { + DR_Node node = new DR_Node("fqdn", "location", "hostName", "1.0"); + + addDrNode(node); + Response response = addDrNode(node); + + assertEquals(409, response.getStatus()); + ApiError responseError = response.readEntity(ApiError.class); + assertNotNull(responseError); + assertEquals("fqdn", responseError.getFields()); + assertEquals("Node fqdn already exists", responseError.getMessage()); + } + + @Test + public void addDr_Node_shouldExecuteSuccessfully() { + DR_Node node = new DR_Node("fqdn", "location", "hostName", "1.0"); + + Response response = addDrNode(node); + + assertEquals(200, response.getStatus()); + assertTrue(response.hasEntity()); + assertDrNodeExistInDB(response.readEntity(DR_Node.class)); + } + + @Test + public void updateDr_Node_shouldReturnError_whenNoLocationAndFqdnProvided() { + DR_Node node = new DR_Node(null, null, "hostName", "1.0"); + Entity<DR_Node> requestedEntity = entity(node, APPLICATION_JSON); + + Response response = testContainer.target("dr_nodes") + .path("fqdn") + .request() + .put(requestedEntity, Response.class); + + assertEquals(400, response.getStatus()); + ApiError responseError = response.readEntity(ApiError.class); + assertNotNull(responseError); + assertEquals("dcaeLocation, fqdn", responseError.getFields()); + } + + @Test + public void updateDr_Node_shouldReturnError_whenNoExistingFqdnProvided() { + DR_Node node = new DR_Node("fqdn", "location", "hostName", "1.0"); + Entity<DR_Node> requestedEntity = entity(node, APPLICATION_JSON); + + Response response = testContainer.target("dr_nodes") + .path("") + .request() + .put(requestedEntity, Response.class); + + assertEquals(405, response.getStatus()); + } + + @Test + public void updateDr_Node_shouldReturnError_whenDrNodeForUpdateDoesNotExistInDb() { + DR_Node node = new DR_Node("fqdn", "location", "hostName", "1.0"); + Entity<DR_Node> requestedEntity = entity(node, APPLICATION_JSON); + + Response response = testContainer.target("dr_nodes") + .path(node.getFqdn()) + .request() + .put(requestedEntity, Response.class); + + assertEquals(404, response.getStatus()); + ApiError responseError = response.readEntity(ApiError.class); + assertNotNull(responseError); + assertEquals("fqdn", responseError.getFields()); + assertEquals("Node " + node.getFqdn() + " does not exist", responseError.getMessage()); + } + + @Test + public void updateDr_Node_ShouldExecuteSuccessfully() { + DR_Node toUpdate = new DR_Node("fqdn", "location", "hostName", "1.0"); + Entity<DR_Node> requestedEntity = entity(toUpdate, APPLICATION_JSON); + + addDrNode(new DR_Node("fqdn", "old_location", "old_hostName", "old_1.0")); + Response response = testContainer.target("dr_nodes") + .path(toUpdate.getFqdn()) + .request() + .put(requestedEntity, Response.class); + + assertEquals(200, response.getStatus()); + assertTrue(response.hasEntity()); + assertEquals(toUpdate, response.readEntity(DR_Node.class)); + } + + @Test + public void deleteDr_Node_shouldReturnError_whenDrNodeForDeleteDoesNotExistInDb() { + Response response = testContainer.target("dr_nodes") + .path("fqdn") + .request() + .delete(); + + assertEquals(404, response.getStatus()); + ApiError responseError = response.readEntity(ApiError.class); + assertNotNull(responseError); + assertEquals("fqdn", responseError.getFields()); + assertEquals("Node fqdn does not exist", responseError.getMessage()); + } + + @Test + public void deleteDr_Node_shouldReturnError_whenNoExistingFqdnProvided() { + Response response = testContainer.target("dr_nodes") + .path("") + .request() + .delete(); + + assertEquals(405, response.getStatus()); + } + + @Test + public void deleteDr_Node_shouldExecuteSuccessfully() { + DR_Node node = new DR_Node("fqdn", "location", "hostName", "1.0"); + + addDrNode(node); + Response response = testContainer.target("dr_nodes") + .path("fqdn") + .request() + .delete(); + + assertEquals(204, response.getStatus()); + } + + @Test + public void getDr_Node_shouldReturnError_whenDrNodeForDeleteDoesNotExistInDb() { + Response response = testContainer.target("dr_nodes") + .path("fqdn") + .request() + .get(); + + assertEquals(404, response.getStatus()); + ApiError responseError = response.readEntity(ApiError.class); + assertNotNull(responseError); + assertEquals("fqdn", responseError.getFields()); + assertEquals("Node fqdn does not exist", responseError.getMessage()); + } + + private Response addDrNode(DR_Node node) { + return testContainer.target("dr_nodes") + .request() + .post(entity(node, APPLICATION_JSON), Response.class); + } + + private void assertDrNodeExistInDB(DR_Node created) { + Response response = testContainer.target("dr_nodes") + .path(created.getFqdn()) + .request() + .get(); + assertEquals(200, response.getStatus()); + assertTrue(response.hasEntity()); + assertEquals(created, response.readEntity(DR_Node.class)); + } + + @Before + public void cleanupDatabase() { + DatabaseClass.clearDatabase(); + } } diff --git a/src/test/java/org/onap/dmaap/dbcapi/resources/DR_PubResourceTest.java b/src/test/java/org/onap/dmaap/dbcapi/resources/DR_PubResourceTest.java index d4f71bb..bf03088 100644 --- a/src/test/java/org/onap/dmaap/dbcapi/resources/DR_PubResourceTest.java +++ b/src/test/java/org/onap/dmaap/dbcapi/resources/DR_PubResourceTest.java @@ -8,9 +8,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. @@ -19,156 +19,264 @@ * ============LICENSE_END========================================================= */ package org.onap.dmaap.dbcapi.resources; -import org.onap.dmaap.dbcapi.model.*; -import org.onap.dmaap.dbcapi.service.*; -import static org.junit.Assert.*; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import java.util.*; -import java.sql.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; -import org.glassfish.jersey.test.JerseyTest; -import org.glassfish.jersey.server.ResourceConfig; import javax.ws.rs.client.Entity; -import javax.ws.rs.core.Application; -import javax.ws.rs.core.Response; import javax.ws.rs.core.MediaType; -import javax.ws.rs.Path; -import javax.ws.rs.GET; - -public class DR_PubResourceTest extends JerseyTest{ - - @Override - protected Application configure() { - return new ResourceConfig() - .register( DR_PubResource.class ) - .register( FeedResource.class ); - } - - private static final String fmt = "%24s: %s%n"; - String d, un, up, f, p; -/* - @Before - public void setUp() throws Exception { - d = "central-onap"; - un = "user1"; - up = "secretW0rd"; - f = "234"; - p = "678"; - } - - @After - public void tearDown() throws Exception { - } -*/ - - - -/* may conflict with test framework! - @Before - public void setUp() throws Exception { - } - - @After - public void tearDown() throws Exception { - } -*/ - - private Feed addFeed( String name, String desc ) { - Feed feed = new Feed( name, "1.0", desc, "dgl", "unrestricted" ); - Entity<Feed> reqEntity = Entity.entity( feed, MediaType.APPLICATION_JSON ); - Response resp = target( "feeds").request().post( reqEntity, Response.class ); - int rc = resp.getStatus(); - System.out.println( "POST feed resp=" + rc ); - assertTrue( rc == 200 || rc == 409 ); - feed = resp.readEntity( Feed.class ); - return feed; - } - - private DR_Pub addPub( String d, String un, String up, String feedId ) { - DR_Pub dr_pub = new DR_Pub( d, un, up, feedId, "" ); - Entity<DR_Pub> reqEntity2 = Entity.entity( dr_pub, MediaType.APPLICATION_JSON); - Response resp = target( "dr_pubs").request().post( reqEntity2, Response.class); - System.out.println( "POST dr_pubs resp=" + resp.getStatus() ); - assertTrue( resp.getStatus() == 201 ); - dr_pub = resp.readEntity( DR_Pub.class ); - - return dr_pub; - } - - private DR_Pub addPubByName( String d, String un, String up, String feedName) { - DR_Pub dr_pub = new DR_Pub( d, un, up, null, "" ); - dr_pub.setFeedName(feedName); - Entity<DR_Pub> reqEntity2 = Entity.entity( dr_pub, MediaType.APPLICATION_JSON); - Response resp = target( "dr_pubs").request().post( reqEntity2, Response.class); - System.out.println( "POST dr_pubs resp=" + resp.getStatus() ); - assertTrue( resp.getStatus() == 201 ); - dr_pub = resp.readEntity( DR_Pub.class ); - - return dr_pub; - } - - @Test - public void GetTest() { - Response resp = target( "dr_pubs").request().get( Response.class ); - System.out.println( "GET dr_pubs resp=" + resp.getStatus() ); - - assertTrue( resp.getStatus() == 200 ); - } - - @Test - public void PostTest() { - - Feed feed = addFeed( "pubPostTest", "post unit test" ); - System.out.println( "fpubPostTest: feedId=" + feed.getFeedId()); - - String d, un, up; - d = "central-onap"; - un = "user1"; - up = "secretW0rd"; - - DR_Pub dr_pub = addPub( d, un, up, feed.getFeedId() ); - } - - @Test - public void PostTestByName() { - - Feed feed = addFeed( "pubPostTest2", "post unit test" ); - System.out.println( "fpubPostTest: feedId=" + feed.getFeedId()); - - String d, un, up; - d = "central-onap"; - un = "user1"; - up = "secretW0rd"; - - DR_Pub dr_pub = addPubByName( d, un, up, "pubPostTest2" ); - } - - @Test - public void PutTest() { - - Feed feed = addFeed( "pubPutTest", "put unit test"); - String d, un, up; - d = "central-onap"; - un = "user1"; - up = "secretW0rd"; - - DR_Pub dr_pub = addPub( d, un, up, feed.getFeedId() ); - - dr_pub.setUserpwd("newSecret"); - Entity<DR_Pub> reqEntity2 = Entity.entity( dr_pub, MediaType.APPLICATION_JSON); - Response resp = target( "dr_pubs") - .path( dr_pub.getPubId() ) - .request() - .put( reqEntity2, Response.class); - System.out.println( "PUT dr_pubs resp=" + resp.getStatus() ); - assertTrue( resp.getStatus() == 200 ); - } - +import javax.ws.rs.core.Response; +import org.glassfish.jersey.server.ResourceConfig; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.onap.dmaap.dbcapi.database.DatabaseClass; +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.testframework.DmaapObjectFactory; + +public class DR_PubResourceTest { + + private static final DmaapObjectFactory DMAAP_OBJECT_FACTORY = new DmaapObjectFactory(); + + private static final String DCAE_LOCATION_NAME = "central-onap"; + private static final String USERNAME = "user1"; + private static final String USRPWD = "secretW0rd"; + private static final String FEED_ID = "someFakeFeedId"; + private static final String PUB_ID = "0"; + private static FastJerseyTestContainer testContainer; + private static TestFeedCreator testFeedCreator; + + @BeforeClass + public static void setUpClass() throws Exception { + //TODO: init is still needed here to assure that dmaap is not null + DatabaseClass.getDmaap().init(DMAAP_OBJECT_FACTORY.genDmaap()); + + testContainer = new FastJerseyTestContainer(new ResourceConfig() + .register(DR_PubResource.class) + .register(FeedResource.class)); + + testContainer.init(); + testFeedCreator = new TestFeedCreator(testContainer); + } + + @AfterClass + public static void tearDownClass() throws Exception { + testContainer.destroy(); + /*TODO: Cannot cleanup yet until still other Resources tests depends on the static DB content + + DatabaseClass.clearDatabase(); + DatabaseClass.getDmaap().remove();*/ + } + + @Before + public void cleanupDatabase() { + DatabaseClass.clearDatabase(); + } + + @Test + public void getDr_Pub_test() { + Response resp = testContainer.target("dr_pubs").request().get(Response.class); + assertTrue(resp.getStatus() == 200); + assertTrue(resp.hasEntity()); + } + + @Test + public void addDr_Pub_shallReturnError_whenNoFeedIdAndFeedNameInPubProvided() { + //given + DR_Pub drPub = new DR_Pub(DCAE_LOCATION_NAME, USERNAME, USRPWD, null, PUB_ID); + Entity<DR_Pub> requestedEntity = Entity.entity(drPub, MediaType.APPLICATION_JSON); + + //when + Response resp = testContainer.target("dr_pubs") + .request() + .post(requestedEntity, Response.class); + + //then + assertEquals(400, resp.getStatus()); + ApiError responseError = resp.readEntity(ApiError.class); + assertNotNull(responseError); + assertEquals("feedName", responseError.getFields()); + } + + @Test + public void addDr_Pub_shallReturnError_whenFeedNameProvided_butFeedNotExist() { + //given + DR_Pub drPub = new DR_Pub(DCAE_LOCATION_NAME, USERNAME, USRPWD, null, PUB_ID); + Entity<DR_Pub> requestedEntity = Entity.entity(drPub, MediaType.APPLICATION_JSON); + drPub.setFeedName("feed_name"); + + + //when + Response resp = testContainer.target("dr_pubs") + .request() + .post(requestedEntity, Response.class); + + //then + assertEquals(404, resp.getStatus()); + ApiError responseError = resp.readEntity(ApiError.class); + assertNotNull(responseError); + assertEquals("feedName", responseError.getFields()); + + } + + @Test + public void addDr_Pub_shallReturnError_whenFeedIdProvided_butFeedNotExist() { + //given + DR_Pub drPub = new DR_Pub(DCAE_LOCATION_NAME, USERNAME, USRPWD, FEED_ID, PUB_ID); + Entity<DR_Pub> requestedEntity = Entity.entity(drPub, MediaType.APPLICATION_JSON); + + //when + Response resp = testContainer.target("dr_pubs") + .request() + .post(requestedEntity, Response.class); + + //then + assertEquals(404, resp.getStatus()); + ApiError responseError = resp.readEntity(ApiError.class); + assertNotNull(responseError); + assertEquals("feedId=" + FEED_ID, responseError.getFields()); + } + + @Test + public void addDr_Pub_shallExecuteSuccessfully_whenValidFeedIdProvided() { + //given + String feedId = assureFeedIsInDB(); + DR_Pub drPub = new DR_Pub(DCAE_LOCATION_NAME, USERNAME, USRPWD, feedId); + Entity<DR_Pub> requestedEntity = Entity.entity(drPub, MediaType.APPLICATION_JSON); + + //when + Response resp = testContainer.target("dr_pubs") + .request() + .post(requestedEntity, Response.class); + + //then + assertEquals(201, resp.getStatus()); + } + + @Test + public void addDr_Pub_shallExecuteSuccessfully_whenValidFeedNameProvided() { + //given + String feedName = "testFeed"; + testFeedCreator.addFeed(feedName, "test feed"); + DR_Pub drPub = new DR_Pub(DCAE_LOCATION_NAME, USERNAME, USRPWD, null, PUB_ID); + drPub.setFeedName(feedName); + Entity<DR_Pub> requestedEntity = Entity.entity(drPub, MediaType.APPLICATION_JSON); + + //when + Response resp = testContainer.target("dr_pubs") + .request() + .post(requestedEntity, Response.class); + + //then + assertEquals(201, resp.getStatus()); + } + + @Test + public void updateDr_Pub_shallExecuteSuccessfully_whenAddingNewPublisher() { + //given + String pubId = "5"; + DR_Pub drPub = new DR_Pub(DCAE_LOCATION_NAME, USERNAME, USRPWD, "feedId", PUB_ID); + Entity<DR_Pub> reqEntity2 = Entity.entity(drPub, MediaType.APPLICATION_JSON); + + //when + Response resp = testContainer.target("dr_pubs") + .path(pubId) + .request() + .put(reqEntity2, Response.class); + + //then + assertEquals(200, resp.getStatus()); + + } + + @Test + public void updateDr_Pub_shallReturnError_whenPathIsWrong() { + //given + DR_Pub drPub = new DR_Pub(DCAE_LOCATION_NAME, USERNAME, USRPWD, FEED_ID, PUB_ID); + Entity<DR_Pub> reqEntity2 = Entity.entity(drPub, MediaType.APPLICATION_JSON); + + //when + Response resp = testContainer.target("dr_pubs") + .path("") + .request() + .put(reqEntity2, Response.class); + + //then + assertEquals(405, resp.getStatus()); + } + + @Test + public void deleteDr_Pub_shouldDeleteObjectWithSuccess() { + //given + String feedId = assureFeedIsInDB(); + DR_Pub dr_pub = addPub(DCAE_LOCATION_NAME, USERNAME, USRPWD, feedId); + + //when + Response resp = testContainer.target("dr_pubs") + .path(dr_pub.getPubId()) + .request() + .delete(); + + //then + assertEquals("Shall delete subscription with success", 204, resp.getStatus()); + assertFalse("No entity object shall be returned", resp.hasEntity()); + } + + @Test + public void deleteDr_Pub_shouldReturnErrorResponse_whenGivenPubIdNotFound() { + //given + String notExistingPubId = "6789"; + + //when + Response resp = testContainer.target("dr_pubs") + .path(notExistingPubId) + .request() + .delete(); + + //then + assertEquals("Shall return error, when trying to delete not existing subscription", 404, resp.getStatus()); + ApiError responseError = resp.readEntity(ApiError.class); + assertNotNull(responseError); + assertEquals("pubId", responseError.getFields()); + } + + @Test + public void get_shallReturnExistingObject() { + //given + String feedId = assureFeedIsInDB(); + DR_Pub dr_Pub = addPub(DCAE_LOCATION_NAME, USERNAME, USRPWD, feedId); + + //when + Response resp = testContainer.target("dr_pubs") + .path(dr_Pub.getPubId()) + .request() + .get(); + + //then + assertEquals("Subscription shall be found", 200, resp.getStatus()); + assertEquals("Retrieved object shall be equal to eh one put into DB", dr_Pub, resp.readEntity(DR_Pub.class)); + } + private DR_Pub addPub(String d, String un, String up, String feedId) { + DR_Pub dr_pub = new DR_Pub(d, un, up, feedId, ""); + Entity<DR_Pub> reqEntity2 = Entity.entity(dr_pub, MediaType.APPLICATION_JSON); + Response resp = testContainer.target("dr_pubs").request().post(reqEntity2, Response.class); + System.out.println("POST dr_pubs resp=" + resp.getStatus()); + assertTrue(resp.getStatus() == 201); + dr_pub = resp.readEntity(DR_Pub.class); + return dr_pub; + } + private String assureFeedIsInDB() { + Feed feed = testFeedCreator.addFeed("SubscriberTestFeed", "feed for DR_Sub testing"); + assertNotNull("Feed shall be added into DB properly", feed); + return feed.getFeedId(); + } } diff --git a/src/test/java/org/onap/dmaap/dbcapi/resources/DR_SubResourceTest.java b/src/test/java/org/onap/dmaap/dbcapi/resources/DR_SubResourceTest.java index 2227870..13b89ea 100644 --- a/src/test/java/org/onap/dmaap/dbcapi/resources/DR_SubResourceTest.java +++ b/src/test/java/org/onap/dmaap/dbcapi/resources/DR_SubResourceTest.java @@ -1,9 +1,8 @@ - /*- * ============LICENSE_START======================================================= * org.onap.dmaap * ================================================================================ - * Copyright (C) 2018 AT&T Intellectual Property. All rights reserved. + * 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. @@ -19,211 +18,417 @@ * ============LICENSE_END========================================================= */ package org.onap.dmaap.dbcapi.resources; -import org.onap.dmaap.dbcapi.model.*; -import org.onap.dmaap.dbcapi.service.*; -import org.onap.dmaap.dbcapi.testframework.DmaapObjectFactory; - -import static org.junit.Assert.*; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import java.util.*; -import java.sql.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; -import org.glassfish.jersey.test.JerseyTest; -import org.glassfish.jersey.server.ResourceConfig; import javax.ws.rs.client.Entity; -import javax.ws.rs.core.Application; -import javax.ws.rs.core.Response; import javax.ws.rs.core.MediaType; -import javax.ws.rs.Path; -import javax.ws.rs.GET; - -public class DR_SubResourceTest extends JerseyTest{ - - static DmaapObjectFactory factory = new DmaapObjectFactory(); - - @Override - protected Application configure() { - return new ResourceConfig() - .register( DR_SubResource.class ) - .register( FeedResource.class ) - .register( DcaeLocationResource.class ) - .register( DmaapResource.class ); - } - - String d, un, up, f, p; - - @Before - public void preTest() throws Exception { - try { - - Dmaap dmaap = factory.genDmaap(); - Entity<Dmaap> reqEntity = Entity.entity( dmaap, MediaType.APPLICATION_JSON ); - Response resp = target( "dmaap").request().post( reqEntity, Response.class ); - System.out.println( resp.getStatus() ); - assertTrue( resp.getStatus() == 200 ); - }catch (Exception e ) { - } - try { - DcaeLocation loc = factory.genDcaeLocation( "central" ); - Entity<DcaeLocation> reqEntity = Entity.entity( loc, MediaType.APPLICATION_JSON ); - Response resp = target( "dcaeLocations").request().post( reqEntity, Response.class ); - System.out.println( "POST dcaeLocation resp=" + resp.getStatus() + " " + resp.readEntity( String.class )); - if ( resp.getStatus() != 409 ) { - assertTrue( resp.getStatus() == 201 ); - } - } catch (Exception e ) { - } - - - } -/* - @Before - public void setUp() throws Exception { - d = "central-onap"; - un = "user1"; - up = "secretW0rd"; - f = "234"; - p = "678"; - } - - @After - public void tearDown() throws Exception { - } -*/ - - - -/* may conflict with test framework! - @Before - public void setUp() throws Exception { - } - - @After - public void tearDown() throws Exception { - } -*/ - - private Feed addFeed( String name, String desc ) { - Feed feed = new Feed( name, "1.0", desc, "dgl", "unrestricted" ); - Entity<Feed> reqEntity = Entity.entity( feed, MediaType.APPLICATION_JSON ); - Response resp = target( "feeds").request().post( reqEntity, Response.class ); - int rc = resp.getStatus(); - System.out.println( "POST feed resp=" + rc ); - assertTrue( rc == 200 || rc == 409 ); - feed = resp.readEntity( Feed.class ); - return feed; - } - - private DR_Sub addSub( String d, String un, String up, String feedId ) { - DR_Sub dr_sub = new DR_Sub( d, un, up, feedId, - "https://subscriber.onap.org/foo", "https://dr-prov/sublog", true ); - - Entity<DR_Sub> reqEntity2 = Entity.entity( dr_sub, MediaType.APPLICATION_JSON); - Response resp = target( "dr_subs").request().post( reqEntity2, Response.class); - System.out.println( "POST dr_subs resp=" + resp.getStatus() ); - assertTrue( resp.getStatus() == 201 ); - dr_sub = resp.readEntity( DR_Sub.class ); - - return dr_sub; - } - private DR_Sub addSubByName( String d, String un, String up, String feedName ) { - DR_Sub dr_sub = new DR_Sub( d, un, up, null, - "https://subscriber.onap.org/foo", "https://dr-prov/sublog", true ); - - dr_sub.setFeedName(feedName); - - Entity<DR_Sub> reqEntity2 = Entity.entity( dr_sub, MediaType.APPLICATION_JSON); - Response resp = target( "dr_subs").request().post( reqEntity2, Response.class); - System.out.println( "POST dr_subs resp=" + resp.getStatus() ); - assertTrue( resp.getStatus() == 201 ); - dr_sub = resp.readEntity( DR_Sub.class ); - - return dr_sub; - } - - @Test - public void GetTest() { - Response resp = target( "dr_subs").request().get( Response.class ); - System.out.println( "GET dr_subs resp=" + resp.getStatus() ); - - assertTrue( resp.getStatus() == 200 ); - } - - @Test - public void PostTest() { - - Feed feed = addFeed( "subPostTest", "post unit test" ); - System.out.println( "subPostTest: feedId=" + feed.getFeedId()); - - String d, un, up; - d = "central-onap"; - un = "user1"; - up = "secretW0rd"; - - DR_Sub dr_pub = addSub( d, un, up, feed.getFeedId() ); - } - - @Test - public void PostTestByName() { - - Feed feed = addFeed( "subPostTest2", "post unit test" ); - System.out.println( "subPostTest2: feedId=" + feed.getFeedId()); - - String d, un, up; - d = "central-onap"; - un = "user1"; - up = "secretW0rd"; - - DR_Sub dr_pub = addSubByName( d, un, up, feed.getFeedName() ); - } - - @Test - public void PutTest() { - - Feed feed = addFeed( "subPutTest", "put unit test"); - String d, un, up; - d = "central-onap"; - un = "user1"; - up = "secretW0rd"; - - DR_Sub dr_sub = addSub( d, un, up, feed.getFeedId() ); - - dr_sub.setUserpwd("newSecret"); - Entity<DR_Sub> reqEntity2 = Entity.entity( dr_sub, MediaType.APPLICATION_JSON); - Response resp = target( "dr_subs") - .path( dr_sub.getSubId() ) - .request() - .put( reqEntity2, Response.class); - System.out.println( "PUT dr_subs resp=" + resp.getStatus() ); - assertTrue( resp.getStatus() == 200 ); - } - -/* - * TODO: figure out how to check delete() response - @Test - public void DelTest() { - - Feed feed = addFeed( "subDelTest", "del unit test"); - String d, un, up; - d = "central-onap"; - un = "user1"; - up = "secretW0rd"; - - DR_Sub dr_sub = addSub( d, un, up, feed.getFeedId() ); - - Entity<DR_Sub> reqEntity2 = Entity.entity( dr_sub, MediaType.APPLICATION_JSON); - Response resp = target( "dr_subs") - .path( dr_sub.getSubId() ) - .request() - .delete(); - System.out.println( "DEL dr_subs resp=" + resp.getStatus() ); - assertTrue( resp.getStatus() == 200 ); - } -*/ +import javax.ws.rs.core.Response; +import org.glassfish.jersey.server.ResourceConfig; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.onap.dmaap.dbcapi.database.DatabaseClass; +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.testframework.DmaapObjectFactory; +public class DR_SubResourceTest { + + private static final DmaapObjectFactory DMAAP_OBJECT_FACTORY = new DmaapObjectFactory(); + + private static final String DCAE_LOCATION_NAME = "central-onap"; + private static final String USERNAME = "user1"; + private static final String USRPWD = "secretW0rd"; + private static final String DELIVERY_URL = "https://subscriber.onap.org/delivery/id"; + private static final String LOG_URL = "https://dr-prov/sublog/id"; + private static final String DELIVERY_URL_TEMPLATE = "https://subscriber.onap.org/delivery/"; + private static final String LOG_URL_TEMPLATE = "https://dr-prov/sublog/"; + private static FastJerseyTestContainer testContainer; + private static TestFeedCreator testFeedCreator; + + @BeforeClass + public static void setUpClass() throws Exception { + //TODO: init is still needed here to assure that dmaap is not null + DatabaseClass.getDmaap().init(DMAAP_OBJECT_FACTORY.genDmaap()); + + testContainer = new FastJerseyTestContainer(new ResourceConfig() + .register(DR_SubResource.class) + .register(FeedResource.class)); + testContainer.init(); + testFeedCreator = new TestFeedCreator(testContainer); + } + + @AfterClass + public static void tearDownClass() throws Exception { + testContainer.destroy(); + /*TODO: Cannot cleanup yet until still other Resources tests depends on the static DB content + + DatabaseClass.clearDatabase(); + DatabaseClass.getDmaap().remove();*/ + } + + @Before + public void cleanupDatabase() { + DatabaseClass.clearDatabase(); + } + + //TODO: figure out generic entity list unmarshall to check the entity list + @Test + public void getDr_Subs_test() { + Response resp = testContainer.target("dr_subs").request().get(Response.class); + System.out.println("GET dr_subs resp=" + resp.getStatus()); + + assertEquals(200, resp.getStatus()); + assertTrue(resp.hasEntity()); + } + + @Test + public void addDr_Sub_shallReturnError_whenNoFeedIdAndFeedNameInSubProvided() { + //given + DR_Sub drSub = new DR_Sub(DCAE_LOCATION_NAME, USERNAME, USRPWD, null, DELIVERY_URL, LOG_URL, true); + Entity<DR_Sub> requestedEntity = Entity.entity(drSub, MediaType.APPLICATION_JSON); + + //when + Response resp = testContainer.target("dr_subs") + .request() + .post(requestedEntity, Response.class); + + //then + assertEquals(400, resp.getStatus()); + ApiError responseError = resp.readEntity(ApiError.class); + assertNotNull(responseError); + assertEquals("feedName", responseError.getFields()); + } + + @Test + public void addDr_Sub_shallReturnError_whenFeedNameProvided_butFeedNotExist() { + //given + String notExistingFeedName = "notRealFead"; + DR_Sub drSub = new DR_Sub(DCAE_LOCATION_NAME, USERNAME, USRPWD, null, DELIVERY_URL, LOG_URL, true); + drSub.setFeedName(notExistingFeedName); + Entity<DR_Sub> requestedEntity = Entity.entity(drSub, MediaType.APPLICATION_JSON); + + //when + Response resp = testContainer.target("dr_subs") + .request() + .post(requestedEntity, Response.class); + + //then + assertEquals(404, resp.getStatus()); + ApiError responseError = resp.readEntity(ApiError.class); + assertNotNull(responseError); + assertEquals("feedName", responseError.getFields()); + } + + @Test + public void addDr_Sub_shallReturnError_whenFeedNameProvided_andManyFeedsWithTheSameNameInDB() { + //given + String notDistinctFeedName = "notDistinctFeedName"; + Feed feed1 = new Feed(notDistinctFeedName, "1.0", "description", "dgl", "unrestricted"); + Feed feed2 = new Feed(notDistinctFeedName, "2.0", "description", "dgl", "unrestricted"); + DatabaseClass.getFeeds().put("1", feed1); + DatabaseClass.getFeeds().put("2", feed2); + DR_Sub drSub = new DR_Sub(DCAE_LOCATION_NAME, USERNAME, USRPWD, null, DELIVERY_URL, LOG_URL, true); + drSub.setFeedName(notDistinctFeedName); + Entity<DR_Sub> requestedEntity = Entity.entity(drSub, MediaType.APPLICATION_JSON); + + //when + Response resp = testContainer.target("dr_subs") + .request() + .post(requestedEntity, Response.class); + + //then + assertEquals(409, resp.getStatus()); + ApiError responseError = resp.readEntity(ApiError.class); + assertNotNull(responseError); + assertEquals("feedName", responseError.getFields()); + } + + @Test + public void addDr_Sub_shallReturnError_whenFeedIdProvided_butFeedNotExist() { + //given + DR_Sub drSub = new DR_Sub(DCAE_LOCATION_NAME, USERNAME, USRPWD, "someFakeFeedId", DELIVERY_URL, LOG_URL, true); + Entity<DR_Sub> requestedEntity = Entity.entity(drSub, MediaType.APPLICATION_JSON); + + //when + Response resp = testContainer.target("dr_subs") + .request() + .post(requestedEntity, Response.class); + + //then + assertEquals(404, resp.getStatus()); + ApiError responseError = resp.readEntity(ApiError.class); + assertNotNull(responseError); + assertTrue(responseError.getFields().contains("feedId")); + } + + @Test + public void addDr_Sub_shallExecuteSuccessfully_whenValidFeedIdProvided() { + //given + String feedId = assureFeedIsInDB(); + DR_Sub drSub = new DR_Sub(DCAE_LOCATION_NAME, USERNAME, USRPWD, feedId, DELIVERY_URL, LOG_URL, true); + Entity<DR_Sub> requestedEntity = Entity.entity(drSub, MediaType.APPLICATION_JSON); + + //when + Response resp = testContainer.target("dr_subs") + .request() + .post(requestedEntity, Response.class); + + //then + assertEquals(201, resp.getStatus()); + assertTrue(resp.hasEntity()); + DR_Sub created = resp.readEntity(DR_Sub.class); + assertSubscriptionExistInDB(created); + } + + @Test + public void addDr_Sub_shallExecuteSuccessfully_whenValidFeedNameProvided() { + //given + String feedName = "testFeed"; + testFeedCreator.addFeed(feedName, "test feed"); + DR_Sub drSub = new DR_Sub(DCAE_LOCATION_NAME, USERNAME, USRPWD, null, DELIVERY_URL, LOG_URL, true); + drSub.setFeedName(feedName); + Entity<DR_Sub> requestedEntity = Entity.entity(drSub, MediaType.APPLICATION_JSON); + + //when + Response resp = testContainer.target("dr_subs") + .request() + .post(requestedEntity, Response.class); + + //then + assertEquals(201, resp.getStatus()); + assertTrue(resp.hasEntity()); + DR_Sub created = resp.readEntity(DR_Sub.class); + assertSubscriptionExistInDB(created); + } + + + @Test + public void updateDr_Sub_shallReturnError_whenNoFeedIdInSubProvided() { + //given + String subId = "1234"; + DR_Sub drSub = new DR_Sub(DCAE_LOCATION_NAME, USERNAME, USRPWD, null, DELIVERY_URL, LOG_URL, true); + Entity<DR_Sub> requestedEntity = Entity.entity(drSub, MediaType.APPLICATION_JSON); + + //when + Response resp = testContainer.target("dr_subs") + .path(subId) + .request() + .put(requestedEntity, Response.class); + + //then + assertEquals(400, resp.getStatus()); + ApiError responseError = resp.readEntity(ApiError.class); + assertNotNull(responseError); + assertEquals("feedId", responseError.getFields()); + } + + @Test + public void updateDr_Sub_shallReturnError_whenNoDCAELocationInSubProvided() { + //given + String subId = "1234"; + DR_Sub drSub = new DR_Sub(null, USERNAME, USRPWD, "someFeedId", DELIVERY_URL, LOG_URL, true); + Entity<DR_Sub> requestedEntity = Entity.entity(drSub, MediaType.APPLICATION_JSON); + + //when + Response resp = testContainer.target("dr_subs") + .path(subId) + .request() + .put(requestedEntity, Response.class); + + //then + assertEquals(400, resp.getStatus()); + ApiError responseError = resp.readEntity(ApiError.class); + assertNotNull(responseError); + assertEquals("dcaeLocationName", responseError.getFields()); + } + + @Test + public void updateDr_Sub_shallReturnError_whenFeedWithGivenIdInSubNotExists() { + //given + String subId = "1234"; + DR_Sub drSub = new DR_Sub(DCAE_LOCATION_NAME, USERNAME, USRPWD, "someFeedId", DELIVERY_URL, LOG_URL, true); + Entity<DR_Sub> requestedEntity = Entity.entity(drSub, MediaType.APPLICATION_JSON); + + //when + Response resp = testContainer.target("dr_subs") + .path(subId) + .request() + .put(requestedEntity, Response.class); + + //then + assertEquals(404, resp.getStatus()); + assertNotNull(resp.readEntity(ApiError.class)); + } + + @Test + public void updateDr_Sub_shallReturnSuccess_whenAddingNewSubscription() { + //given + String subId = "31"; + String feedId = assureFeedIsInDB(); + DR_Sub drSub = new DR_Sub(DCAE_LOCATION_NAME, USERNAME, USRPWD, feedId, null, null, true); + Entity<DR_Sub> requestedEntity = Entity.entity(drSub, MediaType.APPLICATION_JSON); + + //when + Response resp = testContainer.target("dr_subs") + .path(subId) + .request() + .put(requestedEntity, Response.class); + + //then + assertEquals(200, resp.getStatus()); + + DR_Sub createdDrSub = resp.readEntity(DR_Sub.class); + assertNotNull(createdDrSub.getLastMod()); + assertEquals(subId, createdDrSub.getSubId()); + assertEquals(DCAE_LOCATION_NAME, createdDrSub.getDcaeLocationName()); + assertEquals(USERNAME, createdDrSub.getUsername()); + assertEquals(USRPWD, createdDrSub.getUserpwd()); + assertEquals(DELIVERY_URL_TEMPLATE + subId, createdDrSub.getDeliveryURL()); + assertEquals(LOG_URL_TEMPLATE + subId, createdDrSub.getLogURL()); + + assertSubscriptionExistInDB(createdDrSub); + } + + @Test + public void updateDr_Sub_shallReturnSuccess_whenUpdatingExistingSubscription() { + //given + String feedId = assureFeedIsInDB(); + DR_Sub existingDrSub = addSub(DCAE_LOCATION_NAME, USERNAME, USRPWD, feedId); + DR_Sub drSubUpdate = new DR_Sub("newDcaeLocationName", "newUserName", "newUserPwd", feedId, null, null, false); + Entity<DR_Sub> requestedEntity = Entity.entity(drSubUpdate, MediaType.APPLICATION_JSON); + + //when + Response resp = testContainer.target("dr_subs") + .path(existingDrSub.getSubId()) + .request() + .put(requestedEntity, Response.class); + + //then + assertEquals(200, resp.getStatus()); + + DR_Sub updatedDrSub = resp.readEntity(DR_Sub.class); + assertNotNull(updatedDrSub.getLastMod()); + assertEquals(existingDrSub.getSubId(), updatedDrSub.getSubId()); + assertEquals(drSubUpdate.getDcaeLocationName(), updatedDrSub.getDcaeLocationName()); + assertEquals(drSubUpdate.getUsername(), updatedDrSub.getUsername()); + assertEquals(drSubUpdate.getUserpwd(), updatedDrSub.getUserpwd()); + assertEquals(DELIVERY_URL_TEMPLATE + existingDrSub.getSubId(), updatedDrSub.getDeliveryURL()); + assertEquals(LOG_URL_TEMPLATE + existingDrSub.getSubId(), updatedDrSub.getLogURL()); + + assertSubscriptionExistInDB(updatedDrSub); + } + + @Test + public void deleteDr_Sub_shouldDeleteSubscriptionWithSuccess() { + //given + String feedId = assureFeedIsInDB(); + DR_Sub dr_sub = addSub(DCAE_LOCATION_NAME, USERNAME, USRPWD, feedId); + + //when + Response resp = testContainer.target("dr_subs") + .path(dr_sub.getSubId()) + .request() + .delete(); + + //then + assertEquals("Shall delete subscription with success", 204, resp.getStatus()); + assertFalse("No entity object shall be returned",resp.hasEntity()); + assertSubscriptionNotExistInDB(dr_sub.getSubId()); + } + + @Test + public void deleteDr_Sub_shouldReturnErrorResponse_whenGivenSubIdNotFound() { + //given + String notExistingSubId = "6789"; + + //when + Response resp = testContainer.target("dr_subs") + .path(notExistingSubId) + .request() + .delete(); + + //then + assertEquals("Shall return error, when trying to delete not existing subscription", 404, resp.getStatus()); + assertNotNull(resp.readEntity(ApiError.class)); + } + + @Test + public void get_shallReturnExistingObject() { + //given + String feedId = assureFeedIsInDB(); + DR_Sub dr_sub = addSub(DCAE_LOCATION_NAME, USERNAME, USRPWD, feedId); + + //when + Response resp = testContainer.target("dr_subs") + .path(dr_sub.getSubId()) + .request() + .get(); + + //ten + assertEquals("Subscription shall be found",200, resp.getStatus()); + assertEquals("Retrieved object shall be equal to eh one put into DB", dr_sub, resp.readEntity(DR_Sub.class)); + } + + @Test + public void get_shouldReturnError_whenSubWithIdNotFound() { + //given + String notExistingSubId = "1234"; + + //when + Response resp = testContainer.target("dr_subs") + .path(notExistingSubId) + .request() + .get(); + + //then + assertEquals("Subscription shall not be found", 404, resp.getStatus()); + assertNotNull(resp.readEntity(ApiError.class)); + } + + private DR_Sub addSub(String d, String un, String up, String feedId) { + DR_Sub dr_sub = new DR_Sub(d, un, up, feedId, + "https://subscriber.onap.org/foo", "https://dr-prov/sublog", true); + + Entity<DR_Sub> reqEntity2 = Entity.entity(dr_sub, MediaType.APPLICATION_JSON); + Response resp = testContainer.target("dr_subs").request().post(reqEntity2, Response.class); + System.out.println("POST dr_subs resp=" + resp.getStatus()); + assertEquals(201, resp.getStatus()); + dr_sub = resp.readEntity(DR_Sub.class); + + return dr_sub; + } + + private String assureFeedIsInDB() { + Feed feed = testFeedCreator.addFeed("SubscriberTestFeed", "feed for DR_Sub testing"); + assertNotNull("Feed shall be added into DB properly", feed); + return feed.getFeedId(); + } + + + private void assertSubscriptionNotExistInDB(String subId) { + assertEquals(404, testContainer.target("dr_subs") + .path(subId) + .request() + .get() + .getStatus()); + } + + private void assertSubscriptionExistInDB(DR_Sub sub) { + Response response = testContainer.target("dr_subs") + .path(sub.getSubId()) + .request() + .get(); + assertEquals(200, response.getStatus()); + assertTrue(response.hasEntity()); + assertEquals(sub, response.readEntity(DR_Sub.class)); + } } diff --git a/src/test/java/org/onap/dmaap/dbcapi/resources/FastJerseyTestContainer.java b/src/test/java/org/onap/dmaap/dbcapi/resources/FastJerseyTestContainer.java new file mode 100644 index 0000000..8d38a9f --- /dev/null +++ b/src/test/java/org/onap/dmaap/dbcapi/resources/FastJerseyTestContainer.java @@ -0,0 +1,39 @@ +/*- + * ============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 org.glassfish.jersey.test.JerseyTest; + +import javax.ws.rs.core.Application; + +class FastJerseyTestContainer extends JerseyTest { + + FastJerseyTestContainer(Application jaxrsApplication) { + super(jaxrsApplication); + } + + void init() throws Exception { + this.setUp(); + } + + void destroy() throws Exception { + this.tearDown(); + } +}
\ No newline at end of file diff --git a/src/test/java/org/onap/dmaap/dbcapi/resources/MR_ClusterResourceTest.java b/src/test/java/org/onap/dmaap/dbcapi/resources/MR_ClusterResourceTest.java index e4d1da0..7367471 100644 --- a/src/test/java/org/onap/dmaap/dbcapi/resources/MR_ClusterResourceTest.java +++ b/src/test/java/org/onap/dmaap/dbcapi/resources/MR_ClusterResourceTest.java @@ -28,7 +28,9 @@ import javax.ws.rs.core.Response; import org.glassfish.jersey.server.ResourceConfig; import org.glassfish.jersey.test.JerseyTest; +import org.junit.Before; import org.junit.Test; +import org.onap.dmaap.dbcapi.database.DatabaseClass; import org.onap.dmaap.dbcapi.model.DcaeLocation; import org.onap.dmaap.dbcapi.model.MR_Cluster; import org.onap.dmaap.dbcapi.testframework.DmaapObjectFactory; @@ -50,11 +52,12 @@ public class MR_ClusterResourceTest extends JerseyTest { -/* may conflict with test framework! + @Before - public void preTest() throws Exception { + public void init() throws Exception { + DatabaseClass.clearDatabase(); } - +/* @After public void tearDown() throws Exception { } @@ -75,7 +78,7 @@ public class MR_ClusterResourceTest extends JerseyTest { Response resp = target( "mr_clusters").request().post( reqEntity, Response.class ); System.out.println( "POST MR_Cluster resp=" + resp.getStatus() + " " + resp.readEntity( String.class ) ); if (resp.getStatus() != 409 ) { - assertTrue( resp.getStatus() == 201); + assertTrue( resp.getStatus() >= 200 && resp.getStatus() < 300); } resp = target( "mr_clusters"). path( cluster.getDcaeLocationName()).request().get( Response.class ); @@ -94,7 +97,7 @@ public class MR_ClusterResourceTest extends JerseyTest { Response resp = target( "dcaeLocations").request().post( reqEntity, Response.class ); System.out.println( "POST dcaeLocation resp=" + resp.getStatus() + " " + resp.readEntity( String.class )); if ( resp.getStatus() != 409 ) { - assertTrue( resp.getStatus() == 201 ); + assertTrue( resp.getStatus() >= 200 && resp.getStatus() < 300 ); } } catch (Exception e ) { } diff --git a/src/test/java/org/onap/dmaap/dbcapi/resources/RequestTimeLogFilterTest.java b/src/test/java/org/onap/dmaap/dbcapi/resources/RequestTimeLogFilterTest.java new file mode 100644 index 0000000..0c88c0c --- /dev/null +++ b/src/test/java/org/onap/dmaap/dbcapi/resources/RequestTimeLogFilterTest.java @@ -0,0 +1,78 @@ +/*-
+ * ============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 static org.junit.Assert.assertNotNull;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import com.att.eelf.configuration.EELFLogger;
+import java.time.Clock;
+import java.time.Instant;
+import java.time.ZoneId;
+import javax.ws.rs.container.ContainerRequestContext;
+import javax.ws.rs.container.ContainerResponseContext;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnitRunner;
+
+@RunWith(MockitoJUnitRunner.class)
+public class RequestTimeLogFilterTest {
+
+ private Clock clock ;
+ private RequestTimeLogFilter requestTimeLogFilter;
+ public static final long START = 1L;
+ @Mock
+ private ContainerRequestContext requestContext;
+ @Mock
+ private ContainerResponseContext responseContext;
+ @Mock
+ private EELFLogger logger;
+
+
+ @Before
+ public void setup() {
+ clock = Clock.fixed(Instant.parse("1970-01-01T00:00:10Z"), ZoneId.systemDefault());
+ requestTimeLogFilter = new RequestTimeLogFilter(logger, clock);
+ }
+
+ @Test
+ public void shouldHaveDefaultConstructor() {
+ assertNotNull(new RequestTimeLogFilter());
+ }
+
+ @Test
+ public void filterShouldSetStartTimestampProperty() {
+ requestTimeLogFilter.filter(requestContext);
+ verify(requestContext).setProperty("start",clock.millis());
+ }
+
+ @Test
+ public void filterShouldPrintElapsedTime() {
+ when(requestContext.getProperty("start")).thenReturn(START);
+
+ requestTimeLogFilter.filter(requestContext, responseContext);
+
+ verify(logger).info(anyString(),eq(clock.millis() - START));
+ }
+}
\ No newline at end of file diff --git a/src/test/java/org/onap/dmaap/dbcapi/resources/RequiredCheckerTest.java b/src/test/java/org/onap/dmaap/dbcapi/resources/RequiredCheckerTest.java new file mode 100644 index 0000000..f07058b --- /dev/null +++ b/src/test/java/org/onap/dmaap/dbcapi/resources/RequiredCheckerTest.java @@ -0,0 +1,86 @@ +/* + * ============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.hamcrest.BaseMatcher; +import org.hamcrest.Description; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.onap.dmaap.dbcapi.model.ApiError; + +import static javax.ws.rs.core.Response.Status.BAD_REQUEST; +import static org.junit.Assert.fail; + +public class RequiredCheckerTest { + + private static final String NAME = "field_name"; + @Rule + public ExpectedException thrown = ExpectedException.none(); + private RequiredChecker requiredChecker = new RequiredChecker(); + + + @Test + public void required_shouldThrowExceptionWhenObjectIsNull() throws RequiredFieldException { + thrown.expect(RequiredFieldException.class); + thrown.expect(new ApiErrorMatcher(new ApiError(BAD_REQUEST.getStatusCode(), + "missing required field", NAME))); + + requiredChecker.required(NAME, null); + } + + @Test + public void required_shouldThrowExceptionWhenRegexValidationFailed() throws RequiredFieldException { + thrown.expect(RequiredFieldException.class); + thrown.expect(new ApiErrorMatcher(new ApiError(BAD_REQUEST.getStatusCode(), + "value 'with white space' violates regexp check '^\\S+$'", NAME))); + + requiredChecker.required(NAME, "with white space", "^\\S+$"); + } + + @Test + public void required_shouldPassValidation() { + try { + requiredChecker.required(NAME, "value", "^\\S+$"); + } catch (RequiredFieldException e) { + fail("No exception should be thrown"); + } + } + + class ApiErrorMatcher extends BaseMatcher { + + private final ApiError expectedApiEror; + + ApiErrorMatcher(ApiError expectedApiEror) { + this.expectedApiEror = expectedApiEror; + } + + @Override + public boolean matches(Object exception) { + return expectedApiEror.equals(((RequiredFieldException) exception).getApiError()); + } + + @Override + public void describeTo(Description description) { + description.appendText("Following ApiError is expected: ").appendValue(expectedApiEror); + } + } +}
\ No newline at end of file diff --git a/src/test/java/org/onap/dmaap/dbcapi/resources/RequiredFieldExceptionTest.java b/src/test/java/org/onap/dmaap/dbcapi/resources/RequiredFieldExceptionTest.java new file mode 100644 index 0000000..d3dcc42 --- /dev/null +++ b/src/test/java/org/onap/dmaap/dbcapi/resources/RequiredFieldExceptionTest.java @@ -0,0 +1,51 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2018 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. + * 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 static javax.ws.rs.core.Response.Status.BAD_REQUEST; +import static org.junit.Assert.assertEquals; + +import org.junit.Before; +import org.junit.Test; +import org.onap.dmaap.dbcapi.model.ApiError; + +public class RequiredFieldExceptionTest { + ApiError apiError; + RequiredFieldException requiredFieldException; + String expectedValue; + + @Before + public void setUp() { + apiError = new ApiError(BAD_REQUEST.getStatusCode(), "value 'with white space' violates regexp check '^\\S+$'", + "field_name"); + + expectedValue = "RequiredFieldException{" + "apiError=" + apiError + '}'; + + requiredFieldException = new RequiredFieldException(apiError); + } + + @Test + public void testRequiredFieldExceptionToString() { + assertEquals(expectedValue, requiredFieldException.toString()); + } +} diff --git a/src/test/java/org/onap/dmaap/dbcapi/resources/ResponseBuilderTest.java b/src/test/java/org/onap/dmaap/dbcapi/resources/ResponseBuilderTest.java new file mode 100644 index 0000000..ff61d14 --- /dev/null +++ b/src/test/java/org/onap/dmaap/dbcapi/resources/ResponseBuilderTest.java @@ -0,0 +1,96 @@ +/* + * ============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.junit.Test; +import org.onap.dmaap.dbcapi.model.ApiError; + +import javax.ws.rs.core.Response; + +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; +import static org.junit.Assert.assertEquals; + +public class ResponseBuilderTest { + + private static final String OBJECT = "Objcect"; + private static final String MESSAGE = "msg"; + private static final int CODE = 100; + private ResponseBuilder responseBuilder = new ResponseBuilder(); + + @Test + public void success_shouldCreateResponseWithOKStatusCode() { + + Response response = responseBuilder.success(OBJECT); + + assertEquals(OBJECT, response.getEntity()); + assertEquals(Response.Status.OK.getStatusCode(), response.getStatus()); + } + + @Test + public void success_shouldCreateResponseWithDefinedStatusCode() { + + Response response = responseBuilder.success(CODE, OBJECT); + + assertEquals(OBJECT, response.getEntity()); + assertEquals(CODE, response.getStatus()); + } + + @Test + public void unauthorized_shouldCreateCorrectResponse() { + + ApiError error = new ApiError(UNAUTHORIZED.getStatusCode(), MESSAGE, "Authorization"); + Response response = responseBuilder.unauthorized(MESSAGE); + + assertEquals(error, response.getEntity()); + assertEquals(error.getCode(), response.getStatus()); + } + + @Test + public void unavailable_shouldCreateCorrectResponse() { + + ApiError error = new ApiError(SERVICE_UNAVAILABLE.getStatusCode(), + "Request is unavailable due to unexpected condition"); + Response response = responseBuilder.unavailable(); + + assertEquals(error, response.getEntity()); + assertEquals(error.getCode(), response.getStatus()); + } + + @Test + public void notFound_shouldCreateCorrectResponse() { + ApiError error = new ApiError(NOT_FOUND.getStatusCode(), "Requested object not found"); + Response response = responseBuilder.notFound(); + + assertEquals(error, response.getEntity()); + assertEquals(error.getCode(), response.getStatus()); + } + + @Test + public void error_shouldCreateCorrectResponse() { + ApiError error = new ApiError(CODE, "Some Error"); + Response response = responseBuilder.error(error); + + assertEquals(error, response.getEntity()); + assertEquals(error.getCode(), response.getStatus()); + } +}
\ No newline at end of file diff --git a/src/test/java/org/onap/dmaap/dbcapi/resources/TestFeedCreator.java b/src/test/java/org/onap/dmaap/dbcapi/resources/TestFeedCreator.java new file mode 100644 index 0000000..e4dedb1 --- /dev/null +++ b/src/test/java/org/onap/dmaap/dbcapi/resources/TestFeedCreator.java @@ -0,0 +1,49 @@ +/*-
+ * ============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 static org.junit.Assert.assertTrue;
+
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import org.onap.dmaap.dbcapi.model.Feed;
+
+
+public class TestFeedCreator {
+
+
+ private final FastJerseyTestContainer testContainer;
+
+ public TestFeedCreator(FastJerseyTestContainer testContainer) {
+ this.testContainer = testContainer;
+ }
+
+ Feed addFeed(String name, String desc) {
+ Feed feed = new Feed(name, "1.0", desc, "dgl", "unrestricted");
+ Entity<Feed> reqEntity = Entity.entity(feed, MediaType.APPLICATION_JSON);
+ Response resp = testContainer.target("feeds").request().post(reqEntity, Response.class);
+ int rc = resp.getStatus();
+ System.out.println("POST feed resp=" + rc);
+ assertTrue(rc == 200 || rc == 409);
+ feed = resp.readEntity(Feed.class);
+ return feed;
+ }
+}
diff --git a/src/test/java/org/onap/dmaap/dbcapi/resources/TopicResourceTest.java b/src/test/java/org/onap/dmaap/dbcapi/resources/TopicResourceTest.java index b494a59..88840fe 100644 --- a/src/test/java/org/onap/dmaap/dbcapi/resources/TopicResourceTest.java +++ b/src/test/java/org/onap/dmaap/dbcapi/resources/TopicResourceTest.java @@ -30,6 +30,7 @@ import org.glassfish.jersey.server.ResourceConfig; import org.glassfish.jersey.test.JerseyTest; import org.junit.Before; import org.junit.Test; +import org.onap.dmaap.dbcapi.database.DatabaseClass; import org.onap.dmaap.dbcapi.model.DcaeLocation; import org.onap.dmaap.dbcapi.model.Dmaap; import org.onap.dmaap.dbcapi.model.MR_Cluster; @@ -54,15 +55,14 @@ public class TopicResourceTest extends JerseyTest { private static final String fmt = "%24s: %s%n"; - - @Before public void preTest() throws Exception { + DatabaseClass.clearDatabase(); try { Dmaap dmaap = factory.genDmaap(); Entity<Dmaap> reqEntity = Entity.entity( dmaap, MediaType.APPLICATION_JSON ); - Response resp = target( "dmaap").request().post( reqEntity, Response.class ); + Response resp = target( "dmaap").request().put( reqEntity, Response.class ); System.out.println( resp.getStatus() ); assertTrue( resp.getStatus() == 200 ); }catch (Exception e ) { @@ -83,7 +83,7 @@ public class TopicResourceTest extends JerseyTest { Response resp = target( "mr_clusters").request().post( reqEntity, Response.class ); System.out.println( "POST MR_Cluster resp=" + resp.getStatus() + " " + resp.readEntity( String.class ) ); if (resp.getStatus() != 409 ) { - assertTrue( resp.getStatus() == 201); + assertTrue( resp.getStatus() == 200 ); } } catch (Exception e ) { diff --git a/src/test/java/org/onap/dmaap/dbcapi/service/ApiServiceTest.java b/src/test/java/org/onap/dmaap/dbcapi/service/ApiServiceTest.java index 67489e1..dccfadf 100644 --- a/src/test/java/org/onap/dmaap/dbcapi/service/ApiServiceTest.java +++ b/src/test/java/org/onap/dmaap/dbcapi/service/ApiServiceTest.java @@ -19,19 +19,13 @@ */ package org.onap.dmaap.dbcapi.service; -import org.onap.dmaap.dbcapi.model.*; -import org.onap.dmaap.dbcapi.aaf.*; import org.onap.dmaap.dbcapi.authentication.AuthenticationErrorException; import org.onap.dmaap.dbcapi.resources.*; import org.onap.dmaap.dbcapi.testframework.ReflectionHarness; -import static org.junit.Assert.*; - import org.junit.After; import org.junit.Before; import org.junit.Test; -import java.util.List; -import javax.ws.rs.core.Response; public class ApiServiceTest { @@ -55,8 +49,8 @@ public class ApiServiceTest { public void test1() { - //rh.reflect( "org.onap.dmaap.dbcapi.service.ApiService", "get", null ); - + //rh.reflect( "org.onap.dmaap.dbcapi.service.ApiService", "get", null ); + } @Test @@ -65,28 +59,4 @@ public class ApiServiceTest { rh.reflect( "org.onap.dmaap.dbcapi.service.ApiService", "set", v ); } - - @Test - public void test3() { - ApiService nd = new ApiService(); - nd.setAuth( "auth" ); - try { - nd.required( "aName", null, "anExpr" ); - } catch ( RequiredFieldException rfe ) { - } - String out = nd.toString(); - Response r = nd.unauthorized( "aMessage" ); - r = nd.unauthorized(); - r = nd.unavailable(); - r = nd.notFound(); - r = nd.error(); - try { - nd.checkAuthorization( "authval", "/uri/Path", "GET" ); - nd.checkAuthorization(); - } catch ( AuthenticationErrorException aee ) { - } catch ( Exception e ) { - } - } - - } diff --git a/src/test/java/org/onap/dmaap/dbcapi/service/DmaapServiceTest.java b/src/test/java/org/onap/dmaap/dbcapi/service/DmaapServiceTest.java index 7029bd2..c1fa0fd 100644 --- a/src/test/java/org/onap/dmaap/dbcapi/service/DmaapServiceTest.java +++ b/src/test/java/org/onap/dmaap/dbcapi/service/DmaapServiceTest.java @@ -19,16 +19,11 @@ */ package org.onap.dmaap.dbcapi.service; -import org.onap.dmaap.dbcapi.model.*; -import org.onap.dmaap.dbcapi.testframework.ReflectionHarness; -import org.onap.dmaap.dbcapi.aaf.*; - -import static org.junit.Assert.*; - import org.junit.After; import org.junit.Before; import org.junit.Test; -import java.util.List; +import org.onap.dmaap.dbcapi.model.Dmaap; +import org.onap.dmaap.dbcapi.testframework.ReflectionHarness; public class DmaapServiceTest { diff --git a/src/test/java/org/onap/dmaap/dbcapi/service/FeedServiceTest.java b/src/test/java/org/onap/dmaap/dbcapi/service/FeedServiceTest.java index d601bc4..acbc738 100644 --- a/src/test/java/org/onap/dmaap/dbcapi/service/FeedServiceTest.java +++ b/src/test/java/org/onap/dmaap/dbcapi/service/FeedServiceTest.java @@ -95,5 +95,14 @@ public class FeedServiceTest { } + + @Test + public void syncTestHard() { + ApiError err = new ApiError(); + ds.sync( true, err ); + + assert( 200 == err.getCode()); + } + } diff --git a/src/test/java/org/onap/dmaap/dbcapi/service/TopicServiceTest.java b/src/test/java/org/onap/dmaap/dbcapi/service/TopicServiceTest.java index 8fd7b47..f571520 100644 --- a/src/test/java/org/onap/dmaap/dbcapi/service/TopicServiceTest.java +++ b/src/test/java/org/onap/dmaap/dbcapi/service/TopicServiceTest.java @@ -20,6 +20,7 @@ package org.onap.dmaap.dbcapi.service; import org.onap.dmaap.dbcapi.model.*; +import org.onap.dmaap.dbcapi.testframework.DmaapObjectFactory; import org.onap.dmaap.dbcapi.testframework.ReflectionHarness; import static org.junit.Assert.*; @@ -33,17 +34,42 @@ import java.util.ArrayList; public class TopicServiceTest { private static final String fmt = "%24s: %s%n"; - + private static DmaapObjectFactory factory = new DmaapObjectFactory(); ReflectionHarness rh = new ReflectionHarness(); - TopicService ts; - MR_ClusterService mcs; - String locname = "central-onap"; + private TopicService ts; + private MR_ClusterService mcs; + private MR_ClientService cls; + private DcaeLocationService dls; + + DmaapService ds; + String locname; @Before public void setUp() throws Exception { ts = new TopicService(); + assert( ts != null ); + mcs = new MR_ClusterService(); + assert( mcs != null ); + Dmaap nd = factory.genDmaap(); + ds = new DmaapService(); + ds.addDmaap( nd ); + ts = new TopicService(); mcs = new MR_ClusterService(); + cls = new MR_ClientService(); + + dls = new DcaeLocationService(); + DcaeLocation loc = factory.genDcaeLocation( "central" ); + locname = loc.getDcaeLocationName(); + dls.addDcaeLocation( loc ); + loc = factory.genDcaeLocation( "edge"); + + ApiError err = new ApiError(); + + MR_Cluster node = factory.genMR_Cluster( "central" ); + mcs.addMr_Cluster( node, err); + node = factory.genMR_Cluster("edge" ); + mcs.addMr_Cluster(node, err); } @After @@ -68,32 +94,31 @@ public class TopicServiceTest { @Test public void test3() { - Topic topic = new Topic(); + String t = "test3"; + Topic topic = factory.genSimpleTopic( t ); ApiError err = new ApiError(); - topic.setTopicName( "test3" ); - topic.setFqtnStyle( FqtnType.Validator("none") ); - topic.getFqtn(); + Topic nTopic = ts.addTopic( topic, err, false ); if ( nTopic != null ) { - assertTrue( nTopic.getTopicName().equals( topic.getTopicName() )); + assertTrue( nTopic.getTopicName().equals( t )); } } @Test public void test3a() { - Topic topic = new Topic(); + + ApiError err = new ApiError(); - topic.setTopicName( "test3" ); - topic.setFqtnStyle( FqtnType.Validator("none") ); - topic.getFqtn(); + String t = "org.onap.dmaap.interestingTopic"; + Topic topic = factory.genSimpleTopic(t); String f = "mrc.onap.org:3904/events/org.onap.dmaap.interestingTopic"; String c = "publisher"; String[] a = { "sub", "view" }; - MR_Client sub = new MR_Client( locname, f, c, a ); + MR_Client sub = factory.genMR_Client("central", f, c, a ); String[] b = { "pub", "view" }; - MR_Client pub = new MR_Client( "edge", f, c, b ); + MR_Client pub = factory.genMR_Client( "edge", f, c, b ); ArrayList<MR_Client> clients = new ArrayList<MR_Client>(); clients.add( sub ); @@ -106,7 +131,7 @@ public class TopicServiceTest { Topic nTopic = ts.addTopic( topic, err, false ); if ( nTopic != null ) { - assertTrue( nTopic.getTopicName().equals( topic.getTopicName() )); + assertTrue( nTopic.getTopicName().equals( t )); } @@ -122,21 +147,60 @@ public class TopicServiceTest { @Test public void test5() { ApiError err = new ApiError(); -/* - -TODO: find a null pointer in here... - String[] hl = { "host1", "host2", "host3" }; - String loc = "central-onap"; - MR_Cluster cluster = new MR_Cluster( loc, "localhost", "", hl ); - mcs.addMr_Cluster( cluster, err ); - Topic topic = new Topic(); - topic.setTopicName( "test5" ); - topic.setFqtnStyle( FqtnType.Validator("none") ); - topic.setReplicationCase( ReplicationType.Validator("none") ); - String f = topic.getFqtn(); + + Topic topic = factory.genSimpleTopic("test5"); Topic nTopic = ts.updateTopic( topic, err ); -*/ - assertTrue( err.getCode() == 0 ); + + assertTrue( err.getCode() == 200 ); + } + + @Test + public void bridgeTest6() { + ApiError err = new ApiError(); + + String t = "org.onap.dmaap.bridgingTopic"; + Topic topic = factory.genSimpleTopic(t); + topic.setReplicationCase( ReplicationType.REPLICATION_EDGE_TO_CENTRAL ); + + String c = "publisher"; + String[] a = { "sub", "view" }; + MR_Client sub = factory.genMR_Client("central", topic.getFqtn(), c, a ); + String[] b = { "pub", "view" }; + MR_Client pub = factory.genMR_Client( "edge", topic.getFqtn(), c, b ); + ArrayList<MR_Client> clients = new ArrayList<MR_Client>(); + + clients.add( sub ); + clients.add( pub ); + + topic.setClients( clients ); + + Topic nTopic = ts.updateTopic( topic, err ); + + assertTrue( err.getCode() == 200 ); + } + @Test + public void bridgeTest7() { + ApiError err = new ApiError(); + + String t = "org.onap.dmaap.bridgingTopic7"; + Topic topic = factory.genSimpleTopic(t); + topic.setReplicationCase( ReplicationType.REPLICATION_CENTRAL_TO_EDGE ); + + String c = "publisher"; + String[] a = { "sub", "view" }; + MR_Client sub = factory.genMR_Client("edge", topic.getFqtn(), c, a ); + String[] b = { "pub", "view" }; + MR_Client pub = factory.genMR_Client( "central", topic.getFqtn(), c, b ); + ArrayList<MR_Client> clients = new ArrayList<MR_Client>(); + + clients.add( sub ); + clients.add( pub ); + + topic.setClients( clients ); + + Topic nTopic = ts.updateTopic( topic, err ); + + assertTrue( err.getCode() == 200 ); } } diff --git a/src/test/java/org/onap/dmaap/dbcapi/testframework/DmaapObjectFactory.java b/src/test/java/org/onap/dmaap/dbcapi/testframework/DmaapObjectFactory.java index 0bce106..901b4ea 100644 --- a/src/test/java/org/onap/dmaap/dbcapi/testframework/DmaapObjectFactory.java +++ b/src/test/java/org/onap/dmaap/dbcapi/testframework/DmaapObjectFactory.java @@ -99,6 +99,7 @@ public class DmaapObjectFactory { t.setFqtnStyle( FqtnType.Validator("none") ); t.setTopicDescription( "a simple Topic named " + tname ); t.setOwner( "ut"); + t.setFqtn(t.genFqtn()); return t; } diff --git a/src/test/java/org/onap/dmaap/dbcapi/util/PermissionBuilderTest.java b/src/test/java/org/onap/dmaap/dbcapi/util/PermissionBuilderTest.java new file mode 100644 index 0000000..1858e47 --- /dev/null +++ b/src/test/java/org/onap/dmaap/dbcapi/util/PermissionBuilderTest.java @@ -0,0 +1,151 @@ +/*- + * ============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 static org.junit.Assert.*; +import static org.mockito.Mockito.atMost; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import javax.servlet.http.HttpServletRequest; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.runners.MockitoJUnitRunner; +import org.onap.dmaap.dbcapi.model.Dmaap; +import org.onap.dmaap.dbcapi.model.DmaapObject.DmaapObject_Status; +import org.onap.dmaap.dbcapi.service.DmaapService; + +@RunWith(MockitoJUnitRunner.class) +public class PermissionBuilderTest { + + private static final String DMAAP_NAME = "mr"; + private PermissionBuilder permissionBuilder; + @Mock + private DmaapConfig dmaapConfig; + @Mock + private DmaapService dmaapService; + @Mock + private HttpServletRequest request; + + + @Test + public void updateDmaapInstance_shouldSetBootInstance_whenDmaapIsNotInitialized() { + //given + doReturn(null).when(dmaapService).getDmaap(); + permissionBuilder = new PermissionBuilder(dmaapConfig, dmaapService); + + //when + permissionBuilder.updateDmaapInstance(); + + //then + assertEquals(PermissionBuilder.BOOT_INSTANCE, permissionBuilder.getInstance()); + } + + @Test + public void updateDmaapInstance_shouldSetBootInstance_whenDmaapIsInitializedWithDefaultInstance() { + //given + doReturn(provideDefaultInstance()).when(dmaapService).getDmaap(); + permissionBuilder = new PermissionBuilder(dmaapConfig, dmaapService); + + //when + permissionBuilder.updateDmaapInstance(); + + //then + assertEquals(PermissionBuilder.BOOT_INSTANCE, permissionBuilder.getInstance()); + } + + @Test + public void updateDmaapInstance_shouldSetRealInstance_whenDmaapServiceProvidesOne() { + //given + when(dmaapService.getDmaap()).thenReturn(provideDefaultInstance(), provideRealInstance(DMAAP_NAME)); + permissionBuilder = new PermissionBuilder(dmaapConfig, dmaapService); + + //when + permissionBuilder.updateDmaapInstance(); + + //then + assertEquals(DMAAP_NAME, permissionBuilder.getInstance()); + } + + @Test + public void updateDmaapInstance_shouldNotUpdateDmaapInstance_whenAlreadyInitializedWithRealInstance() { + //given + when(dmaapService.getDmaap()).thenReturn(provideRealInstance(DMAAP_NAME), provideRealInstance("newName")); + permissionBuilder = new PermissionBuilder(dmaapConfig, dmaapService); + + //when + permissionBuilder.updateDmaapInstance(); + + //then + assertEquals(DMAAP_NAME, permissionBuilder.getInstance()); + verify(dmaapService, atMost(1)).getDmaap(); + } + + @Test + public void buildPermission_shouldBuildPermissionWithBootInstance() { + //given + String path = "/dmaap"; + String method = "GET"; + initPermissionBuilder(path, method, provideDefaultInstance()); + + //when + String permission = permissionBuilder.buildPermission(request); + + //then + assertEquals("org.onap.dmaap-bc.api.dmaap|boot|GET", permission); + } + + @Test + public void buildPermission_shouldBuildPermissionWithRealInstance() { + //given + String path = "/subpath/topics/"; + String method = "GET"; + initPermissionBuilder(path, method, provideRealInstance(DMAAP_NAME)); + + //when + String permission = permissionBuilder.buildPermission(request); + + //then + assertEquals("org.onap.dmaap-bc.api.topics|mr|GET", permission); + } + + private void initPermissionBuilder(String path, String method, Dmaap dmaapInstance) { + when(dmaapConfig.getProperty(PermissionBuilder.API_NS_PROP, PermissionBuilder.DEFAULT_API_NS)) + .thenReturn(PermissionBuilder.DEFAULT_API_NS); + when(dmaapService.getDmaap()).thenReturn(dmaapInstance); + permissionBuilder = new PermissionBuilder(dmaapConfig, dmaapService); + + when(request.getPathInfo()).thenReturn(path); + when(request.getMethod()).thenReturn(method); + } + + private Dmaap provideDefaultInstance() { + return new Dmaap("0", "", "", "", "", "", "", ""); + } + + private Dmaap provideRealInstance(String dmaapName) { + Dmaap dmaap = new Dmaap("1", "org.onap.dmaap", dmaapName, "https://dmaap-dr-prov:8443", "", "DCAE_MM_AGENT", "", ""); + dmaap.setStatus(DmaapObject_Status.VALID); + return dmaap; + } + +}
\ No newline at end of file diff --git a/version.properties b/version.properties index c811740..8a9bf52 100644 --- a/version.properties +++ b/version.properties @@ -27,7 +27,7 @@ major=1 minor=0 -patch=23 +patch=26 base_version=${major}.${minor}.${patch} # Release must be completed with git revision # in Jenkins |