diff options
author | ATT default cloud user <dgl@research.att.com> | 2017-08-31 21:01:21 +0000 |
---|---|---|
committer | ATT default cloud user <dgl@research.att.com> | 2017-08-31 21:09:25 +0000 |
commit | a05efb7b7b3cfc77f5e3fda11e8434834829f56a (patch) | |
tree | a66167cebfe583a60e09fd0a597327025dbd3c89 /src/main/java | |
parent | 256e95421e478b6fe7a9af77f5681255329cab99 (diff) |
DMAAP-83 Initial code import
Change-Id: Ic059aaadde5ea30d98e5968457a5a8ca2db703bf
Signed-off-by: ATT default cloud user <dgl@research.att.com>
Diffstat (limited to 'src/main/java')
75 files changed, 11116 insertions, 0 deletions
diff --git a/src/main/java/org/onap/dmaap/dbcapi/aaf/AafConnection.java b/src/main/java/org/onap/dmaap/dbcapi/aaf/AafConnection.java new file mode 100644 index 0000000..b7c02dd --- /dev/null +++ b/src/main/java/org/onap/dmaap/dbcapi/aaf/AafConnection.java @@ -0,0 +1,271 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2017 AT&T 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.aaf; + + + + + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.net.ProtocolException; +import java.net.URL; +import java.net.UnknownHostException; + +import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.SSLHandshakeException; + +import org.apache.commons.codec.binary.Base64; +import org.onap.dmaap.dbcapi.logging.BaseLoggingClass; +import org.onap.dmaap.dbcapi.logging.DmaapbcLogMessageEnum; +import org.onap.dmaap.dbcapi.service.DmaapService; + + +public class AafConnection extends BaseLoggingClass { + + + + + + private String aafCred; + + + private HttpsURLConnection uc; + + + public AafConnection( String cred ) { + aafCred = cred; + } + + + private boolean makeConnection( String pURL ) { + + try { + URL u = new URL( pURL ); + uc = (HttpsURLConnection) u.openConnection(); + uc.setInstanceFollowRedirects(false); + logger.info( "successful connect to " + pURL ); + return(true); + } catch (Exception e) { + errorLogger.error(DmaapbcLogMessageEnum.HTTP_CONNECTION_ERROR, pURL, e.getMessage() ); + e.printStackTrace(); + 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( DmaapbcLogMessageEnum.IO_EXCEPTION, ex.getMessage()); + } + + return sb.toString(); + } + + + + public int postAaf( AafObject obj, String pURL ) { + logger.info( "entry: postAaf() to " + pURL ); + String auth = "Basic " + Base64.encodeBase64String(aafCred.getBytes()); + int rc = -1; + + + if ( ! makeConnection( pURL ) ) { + return rc; + }; + + + byte[] postData = obj.getBytes(); + //logger.info( "post fields=" + postData ); //byte isn't very readable + String responsemessage = null; + String responseBody = null; + + try { + if (auth != null) { + uc.setRequestProperty("Authorization", auth); + } + 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 { + uc.connect(); + os = uc.getOutputStream(); + os.write( postData ); + + } 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) { + } + } catch ( SSLHandshakeException she ) { + errorLogger.error( DmaapbcLogMessageEnum.SSL_HANDSHAKE_ERROR, pURL); + } + try { + rc = uc.getResponseCode(); + } catch ( SSLHandshakeException she ) { + errorLogger.error( DmaapbcLogMessageEnum.SSL_HANDSHAKE_ERROR, pURL); + rc = 500; + return rc; + } + 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); + } + } + } + if ( rc >= 200 && rc < 300 ) { + responseBody = bodyToString( uc.getInputStream() ); + logger.info( "responseBody=" + responseBody ); + } else { + logger.warn( "Unsuccessful response: " + responsemessage ); + } + + } catch (Exception e) { + System.err.println("Unable to read response " ); + e.printStackTrace(); + } + finally { + try { + uc.disconnect(); + } catch ( Exception e ) {} + } + //return responseBody; + + return rc; + + } + + public int delAaf(AafObject obj, String pURL) { + logger.info( "entry: delAaf() to " + pURL ); + String auth = "Basic " + Base64.encodeBase64String(aafCred.getBytes()); + int rc = -1; + + + if ( ! makeConnection( pURL ) ) { + return rc; + }; + + + byte[] postData = obj.getBytes(); + //logger.info( "post fields=" + postData ); //byte isn't very readable + String responsemessage = null; + String responseBody = null; + + try { + if (auth != null) { + uc.setRequestProperty("Authorization", auth); + } + uc.setRequestMethod("DELETE"); + 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 { + uc.connect(); + os = uc.getOutputStream(); + os.write( postData ); + + } 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) { + } + } catch ( SSLHandshakeException she ) { + errorLogger.error( DmaapbcLogMessageEnum.SSL_HANDSHAKE_ERROR, pURL); + } + try { + rc = uc.getResponseCode(); + } catch ( SSLHandshakeException she ) { + errorLogger.error( DmaapbcLogMessageEnum.SSL_HANDSHAKE_ERROR, pURL); + rc = 500; + return rc; + } + 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); + } + } + } + if ( rc >= 200 && rc < 300 ) { + responseBody = bodyToString( uc.getInputStream() ); + logger.info( "responseBody=" + responseBody ); + } else { + logger.warn( "Unsuccessful response: " + responsemessage ); + } + + } catch (Exception e) { + System.err.println("Unable to read response " ); + e.printStackTrace(); + } + //return responseBody; + + return rc; + + } + + +} diff --git a/src/main/java/org/onap/dmaap/dbcapi/aaf/AafDecrypt.java b/src/main/java/org/onap/dmaap/dbcapi/aaf/AafDecrypt.java new file mode 100644 index 0000000..c478752 --- /dev/null +++ b/src/main/java/org/onap/dmaap/dbcapi/aaf/AafDecrypt.java @@ -0,0 +1,56 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2017 AT&T 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.aaf; + +import java.io.IOException; + +import org.onap.dmaap.dbcapi.logging.BaseLoggingClass; +import org.onap.dmaap.dbcapi.logging.DmaapbcLogMessageEnum; +import org.onap.dmaap.dbcapi.util.DmaapConfig; + +public class AafDecrypt extends BaseLoggingClass { + String dClass = null; + DecryptionInterface dec = null; + + public AafDecrypt() { + DmaapConfig p = (DmaapConfig)DmaapConfig.getConfig(); + dClass = p.getProperty( "AafDecryption.Class", "org.openecomp.dmaapbc.aaf.ClearDecrypt"); + try { + dec = (DecryptionInterface) (Class.forName(dClass).newInstance()); + dec.init( p.getProperty("CredentialCodecKeyfile", "LocalKey")); + } catch (Exception ee ) { + errorLogger.error(DmaapbcLogMessageEnum.UNEXPECTED_CONDITION, "attempting to instantiate " + dClass ); + } + } + + public String decrypt( String encPwd ) { + + String pwd = "notDecrypted"; + try { + pwd = dec.decrypt( encPwd ); + } catch( IOException io ) { + errorLogger.error(DmaapbcLogMessageEnum.DECRYPT_IO_ERROR, dClass, encPwd ); + } + + return pwd; + + } + +} diff --git a/src/main/java/org/onap/dmaap/dbcapi/aaf/AafObject.java b/src/main/java/org/onap/dmaap/dbcapi/aaf/AafObject.java new file mode 100644 index 0000000..07f171a --- /dev/null +++ b/src/main/java/org/onap/dmaap/dbcapi/aaf/AafObject.java @@ -0,0 +1,33 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2017 AT&T 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.aaf; + +import java.nio.charset.StandardCharsets; + +public abstract class AafObject { + + abstract String toJSON(); + + public byte[] getBytes() { + return toJSON().getBytes(StandardCharsets.UTF_8); + } + +} diff --git a/src/main/java/org/onap/dmaap/dbcapi/aaf/AafService.java b/src/main/java/org/onap/dmaap/dbcapi/aaf/AafService.java new file mode 100644 index 0000000..727ec19 --- /dev/null +++ b/src/main/java/org/onap/dmaap/dbcapi/aaf/AafService.java @@ -0,0 +1,180 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2017 AT&T 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.aaf; + +import java.io.IOException; + +import org.apache.log4j.Logger; +import org.onap.dmaap.dbcapi.logging.BaseLoggingClass; +import org.onap.dmaap.dbcapi.logging.DmaapbcLogMessageEnum; +import org.onap.dmaap.dbcapi.util.DmaapConfig; + +public class AafService extends BaseLoggingClass { + public enum ServiceType { + AAF_Admin, + AAF_TopicMgr + } + + private AafConnection aaf; + private ServiceType ctype; + private String aafURL ; + + private String getCred( boolean wPwd ) { + String mechIdProperty = null; + String pwdProperty = null; + DmaapConfig p = (DmaapConfig)DmaapConfig.getConfig(); + AafDecrypt decryptor = new AafDecrypt(); + + if ( ctype == ServiceType.AAF_Admin ) { + mechIdProperty = "aaf.AdminUser"; + pwdProperty = "aaf.AdminPassword"; + } else if ( ctype == ServiceType.AAF_TopicMgr ){ + mechIdProperty = "aaf.TopicMgrUser"; + pwdProperty = "aaf.TopicMgrPassword"; + } else { + logger.error( "Unexpected case for AAF credential type: " + ctype ); + return null; + } + String user = p.getProperty( mechIdProperty, "noMechId@domain.netset.com" ); + //String dClass = p.getProperty( "AafDecryption.Class", "org.openecomp.dmaapbc.aaf.ClearDecrypt"); + String pwd = ""; + String encPwd = p.getProperty( pwdProperty, "notSet" ); + //DecryptionInterface dec = null; + //try { + // dec = (DecryptionInterface) (Class.forName(dClass).newInstance()); + // dec.init( p.getProperty("CredentialCodecKeyfile", "LocalKey")); + //} catch (Exception ee ) { + // errorLogger.error(DmaapbcLogMessageEnum.UNEXPECTED_CONDITION, "attempting to use " + dClass + " to decrypt " + encPwd ); + //} + //try { + // pwd = dec.decrypt( encPwd ); + //} catch( IOException io ) { + // errorLogger.error(DmaapbcLogMessageEnum.DECRYPT_IO_ERROR, dClass, encPwd ); + //} + + pwd = decryptor.decrypt(encPwd); + + if ( wPwd ) { + return user + ":" + pwd; + } else { + return user; + } + + + } + + public AafService(ServiceType t ) { + DmaapConfig p = (DmaapConfig)DmaapConfig.getConfig(); + aafURL = p.getProperty( "aaf.URL", "https://authentication.domain.netset.com:8095/proxy/"); + initAafService( t ); + } + public AafService( ServiceType t, String url ) { + aafURL = url; + initAafService( t ); + } + + private void initAafService( ServiceType t ) { + ctype = t; + aaf = new AafConnection( getCred( true ) ); + } + + public int addPerm(DmaapPerm perm) { + + int rc = -1; + logger.info( "entry: addPerm() " ); + String pURL = aafURL + "authz/perm"; + rc = aaf.postAaf( perm, pURL ); + switch( rc ) { + case 401: + case 403: + errorLogger.error(DmaapbcLogMessageEnum.AAF_CREDENTIAL_ERROR, getCred( false ) ); + System.exit(1); + case 409: + logger.warn( "Perm already exists. Possible conflict."); + break; + + case 201: + logger.info( "expected response" ); + break; + default : + logger.error( "Unexpected response: " + rc ); + break; + } + + return rc; + } + public int addGrant(DmaapGrant grant ) { + + int rc = -1; + logger.info( "entry: addGrant() " ); + + String pURL = aafURL + "authz/role/perm"; + rc = aaf.postAaf( grant, pURL ); + switch( rc ) { + case 401: + case 403: + errorLogger.error(DmaapbcLogMessageEnum.AAF_CREDENTIAL_ERROR, getCred( false ) ); + System.exit(1); + break; + + case 409: + logger.warn( "Perm already exists. Possible conflict."); + break; + + case 201: + logger.info( "expected response" ); + break; + default : + logger.error( "Unexpected response: " + rc ); + break; + } + + return rc; + } + + public int delGrant( DmaapGrant grant ) { + int rc = -1; + logger.info( "entry: delGrant() " ); + + String pURL = aafURL + "authz/role/:" + grant.getRole() + "/perm"; + rc = aaf.delAaf( grant, pURL ); + switch( rc ) { + case 401: + case 403: + errorLogger.error(DmaapbcLogMessageEnum.AAF_CREDENTIAL_ERROR, getCred( false ) ); + System.exit(1); + break; + + case 404: + logger.warn( "Perm not found...ignore"); + break; + + case 200: + logger.info( "expected response" ); + break; + default : + logger.error( "Unexpected response: " + rc ); + break; + } + + return rc; + } +} diff --git a/src/main/java/org/onap/dmaap/dbcapi/aaf/ClearDecrypt.java b/src/main/java/org/onap/dmaap/dbcapi/aaf/ClearDecrypt.java new file mode 100644 index 0000000..fe3e3e7 --- /dev/null +++ b/src/main/java/org/onap/dmaap/dbcapi/aaf/ClearDecrypt.java @@ -0,0 +1,42 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2017 AT&T 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.aaf; + +import java.io.IOException; + +public class ClearDecrypt implements DecryptionInterface { + + @Override + public String decrypt(String enc) throws IOException { + return enc; + } + + @Override + public String valueOf(String s) { + return s; + } + + @Override + public boolean init(String codecFname) { + return false; + } + +} diff --git a/src/main/java/org/onap/dmaap/dbcapi/aaf/DecryptionInterface.java b/src/main/java/org/onap/dmaap/dbcapi/aaf/DecryptionInterface.java new file mode 100644 index 0000000..eda6465 --- /dev/null +++ b/src/main/java/org/onap/dmaap/dbcapi/aaf/DecryptionInterface.java @@ -0,0 +1,30 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2017 AT&T 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.aaf; + +import java.io.IOException; + +public interface DecryptionInterface { + public boolean init( String codecFname ); + public String decrypt(String enc) throws IOException; + public String valueOf( String s); + +} diff --git a/src/main/java/org/onap/dmaap/dbcapi/aaf/DmaapGrant.java b/src/main/java/org/onap/dmaap/dbcapi/aaf/DmaapGrant.java new file mode 100644 index 0000000..90668be --- /dev/null +++ b/src/main/java/org/onap/dmaap/dbcapi/aaf/DmaapGrant.java @@ -0,0 +1,67 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2017 AT&T 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.aaf; + +import org.apache.log4j.Logger; + +public class DmaapGrant extends AafObject { + static final Logger logger = Logger.getLogger(DmaapGrant.class); + + private DmaapPerm perm; + private String role; + + public DmaapGrant(){ + + } + + public DmaapGrant( DmaapPerm p, String r ) { + this.perm = p; + this.role = r; + } + + public DmaapPerm getPerm() { + return perm; + } + + public void setPerm(DmaapPerm perm) { + this.perm = perm; + } + + public String getRole() { + return role; + } + + public void setRole(String role) { + this.role = role; + } + + public String toJSON() { + + String postJSON = String.format(" { \"perm\": %s, \"role\": \"%s\"}", + this.perm.toJSON(), + this.getRole() ); + logger.info( "returning JSON: " + postJSON); + + return postJSON; + } + + +} diff --git a/src/main/java/org/onap/dmaap/dbcapi/aaf/DmaapPerm.java b/src/main/java/org/onap/dmaap/dbcapi/aaf/DmaapPerm.java new file mode 100644 index 0000000..1893a71 --- /dev/null +++ b/src/main/java/org/onap/dmaap/dbcapi/aaf/DmaapPerm.java @@ -0,0 +1,71 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2017 AT&T 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.aaf; + +import org.apache.log4j.Logger; + + +public class DmaapPerm extends AafObject { + static final Logger logger = Logger.getLogger(DmaapPerm.class); + + private String permission; + private String ptype; + private String action; + + public DmaapPerm(String permission, String ptype, String action) { + super(); + this.permission = permission; + this.ptype = ptype; + this.action = action; + } + public String getPermission() { + return permission; + } + public void setPermission(String permission) { + this.permission = permission; + } + public String getPtype() { + return ptype; + } + public void setPtype(String ptype) { + this.ptype = ptype; + } + public String getAction() { + return action; + } + public void setAction(String action) { + this.action = action; + } + public String toJSON() { + + String postJSON = String.format(" { \"type\": \"%s\", \"instance\": \"%s\", \"action\": \"%s\"}", + this.getPermission(), + this.getPtype(), + this.getAction() ); + logger.info( "returning JSON: " + postJSON); + + return postJSON; + } + + + + +} diff --git a/src/main/java/org/onap/dmaap/dbcapi/aaf/authentication/ApiPermissionInterface.java b/src/main/java/org/onap/dmaap/dbcapi/aaf/authentication/ApiPermissionInterface.java new file mode 100644 index 0000000..acc5da9 --- /dev/null +++ b/src/main/java/org/onap/dmaap/dbcapi/aaf/authentication/ApiPermissionInterface.java @@ -0,0 +1,28 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2017 AT&T 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.aaf.authentication; + +import org.onap.dmaap.dbcapi.aaf.DmaapPerm; + +public interface ApiPermissionInterface { + public void check( String mechid, String pwd, DmaapPerm p ) throws AuthenticationErrorException; + +} diff --git a/src/main/java/org/onap/dmaap/dbcapi/aaf/authentication/ApiPerms.java b/src/main/java/org/onap/dmaap/dbcapi/aaf/authentication/ApiPerms.java new file mode 100644 index 0000000..478b772 --- /dev/null +++ b/src/main/java/org/onap/dmaap/dbcapi/aaf/authentication/ApiPerms.java @@ -0,0 +1,167 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2017 AT&T 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.aaf.authentication; + +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; + +import org.onap.dmaap.dbcapi.aaf.AafService; +import org.onap.dmaap.dbcapi.aaf.DmaapGrant; +import org.onap.dmaap.dbcapi.aaf.DmaapPerm; +import org.onap.dmaap.dbcapi.aaf.AafService.ServiceType; +import org.onap.dmaap.dbcapi.logging.BaseLoggingClass; +import org.onap.dmaap.dbcapi.logging.DmaapbcLogMessageEnum; +import org.onap.dmaap.dbcapi.model.Dmaap; +import org.onap.dmaap.dbcapi.service.DmaapService; +import org.onap.dmaap.dbcapi.util.DmaapConfig; + +public class ApiPerms extends BaseLoggingClass { + + private static class PermissionMap { + static final EELFLogger logger = EELFManager.getInstance().getLogger( PermissionMap.class ); + static final EELFLogger errorLogger = EELFManager.getInstance().getErrorLogger(); + String uri; + String action; + String[] roles; + + public String getUri() { + return uri; + } + public void setUri(String uri) { + this.uri = uri; + } + public String getAction() { + return action; + } + public void setAction(String action) { + this.action = action; + } + + public String[] getRoles() { + return roles; + } + public void setRoles(String[] roles) { + this.roles = roles; + } + + private PermissionMap( String u, String a, String[] r ) { + this.setUri(u); + this.setAction(a); + this.setRoles(r); + } + + static public void initMap( PermissionMap[] pmap, String instance ) { + + DmaapConfig p = (DmaapConfig)DmaapConfig.getConfig(); + String api = p.getProperty("ApiNamespace", "apiNamespace.not.set"); + + // this is needed because PE AAF may be a different instance than AAF used by MR + String peEnv = p.getProperty("PeAafEnvironment", "notSet"); + String url = p.getProperty( new String( "PeAafUrl." + peEnv ), "URL.not.set" ); + logger.info( "PeAafEnvironment=" + peEnv + " using URL " + url); + AafService aaf = new AafService(ServiceType.AAF_Admin, url ); + + for ( int i = 0; i < pmap.length ; i++ ) { + String uri = new String( api + "." + pmap[i].getUri()); + DmaapPerm perm = new DmaapPerm( uri, instance, pmap[i].getAction() ); + int rc = aaf.addPerm( perm ); + if ( rc != 201 && rc != 409 ) { + errorLogger.error( DmaapbcLogMessageEnum.AAF_UNEXPECTED_RESPONSE, Integer.toString(rc), "add perm", perm.toString() ); + + } + for( String r: pmap[i].getRoles()) { + String fr = new String( api + "." + r ); + logger.debug( "i:" + i + " granting perm " + perm.toString()+ " to role=" + fr ); + DmaapGrant grant = new DmaapGrant( perm, fr ); + rc = aaf.addGrant( grant ); + if ( rc != 201 && rc != 409 ) { + errorLogger.error( DmaapbcLogMessageEnum.AAF_UNEXPECTED_RESPONSE, Integer.toString(rc), "grant perm", perm.toString() ); + } + } + + } + } + } + + static PermissionMap[] bootMap = { + new PermissionMap( "dmaap", "GET", new String[] { "Controller" }), + new PermissionMap( "dmaap", "POST", new String[] { "Controller" }), + new PermissionMap( "dmaap", "PUT", new String[] { "Controller" }), + new PermissionMap( "dmaap", "DELETE", new String[] { "Controller" }) + + }; + + static PermissionMap[] envMap = { + new PermissionMap( "dmaap", "GET", new String[] { "Controller", "Orchestrator", "Inventory", "Metrics", "PortalUser" }), + new PermissionMap( "dmaap", "POST", new String[] { "Controller" } ), + new PermissionMap( "dmaap", "PUT", new String[] { "Controller" }), + new PermissionMap( "dmaap", "DELETE", new String[] { "Controller" }), + new PermissionMap( "bridge", "GET", new String[] { "Metrics" }), + //new PermissionMap( "bridge", "POST", new String[] { "Metrics" } ), + //new PermissionMap( "bridge", "PUT", new String[] { "Metrics" }), + //new PermissionMap( "bridge", "DELETE", new String[] { "Metrics" }), + new PermissionMap( "dcaeLocations", "GET", new String[] { "Controller", "Orchestrator", "Inventory", "Metrics", "PortalUser" }), + new PermissionMap( "dcaeLocations", "POST", new String[] { "Controller" } ), + new PermissionMap( "dcaeLocations", "PUT", new String[] { "Controller" }), + new PermissionMap( "dcaeLocations", "DELETE", new String[] { "Controller" }), + new PermissionMap( "dr_nodes", "GET", new String[] { "Controller", "Orchestrator", "Inventory", "PortalUser" }), + new PermissionMap( "dr_nodes", "POST", new String[] { "Controller" } ), + new PermissionMap( "dr_nodes", "PUT", new String[] { "Controller" }), + new PermissionMap( "dr_nodes", "DELETE", new String[] { "Controller" }), + new PermissionMap( "dr_pubs", "GET", new String[] { "Controller", "Orchestrator", "Inventory", "Metrics", "PortalUser" }), + new PermissionMap( "dr_pubs", "POST", new String[] { "Controller", "Orchestrator","PortalUser" } ), + new PermissionMap( "dr_pubs", "PUT", new String[] { "Controller", "Orchestrator","PortalUser" }), + new PermissionMap( "dr_pubs", "DELETE", new String[] { "Controller", "Orchestrator","PortalUser" }), + new PermissionMap( "dr_subs", "GET", new String[] { "Controller", "Orchestrator", "Inventory", "Metrics", "PortalUser" }), + new PermissionMap( "dr_subs", "POST", new String[] { "Controller", "Orchestrator","PortalUser" } ), + new PermissionMap( "dr_subs", "PUT", new String[] { "Controller", "Orchestrator","PortalUser" }), + new PermissionMap( "dr_subs", "DELETE", new String[] { "Controller", "Orchestrator","PortalUser" }), + new PermissionMap( "feeds", "GET", new String[] { "Controller", "Orchestrator", "Inventory", "Metrics", "PortalUser" }), + new PermissionMap( "feeds", "POST", new String[] { "Controller", "Orchestrator","PortalUser" } ), + new PermissionMap( "feeds", "PUT", new String[] { "Controller", "Orchestrator", "PortalUser" }), + new PermissionMap( "feeds", "DELETE", new String[] { "Controller", "PortalUser" }), + new PermissionMap( "mr_clients", "GET", new String[] { "Controller", "Orchestrator", "Inventory", "Metrics", "PortalUser" }), + new PermissionMap( "mr_clients", "POST", new String[] { "Controller","Orchestrator", "PortalUser" } ), + new PermissionMap( "mr_clients", "PUT", new String[] { "Controller", "Orchestrator","PortalUser" }), + new PermissionMap( "mr_clients", "DELETE", new String[] { "Controller","Orchestrator", "PortalUser" }), + new PermissionMap( "mr_clusters", "GET", new String[] { "Controller", "Orchestrator", "Inventory", "Metrics", "PortalUser" }), + new PermissionMap( "mr_clusters", "POST", new String[] { "Controller" } ), + new PermissionMap( "mr_clusters", "PUT", new String[] { "Controller" }), + new PermissionMap( "mr_clusters", "DELETE", new String[] { "Controller" }), + new PermissionMap( "topics", "GET", new String[] { "Controller", "Orchestrator", "Inventory", "Metrics", "PortalUser" }), + new PermissionMap( "topics", "POST", new String[] { "Controller", "Orchestrator" } ), + new PermissionMap( "topics", "PUT", new String[] { "Controller", "Orchestrator" }), + new PermissionMap( "topics", "DELETE", new String[] { "Controller", "Orchestrator" }) + }; + + public void setBootMap() { + String instance = "boot"; + PermissionMap.initMap( bootMap, instance ); + } + + public void setEnvMap() { + Dmaap dmaap = new DmaapService().getDmaap(); + String dmaap_name = dmaap.getDmaapName(); + PermissionMap.initMap( envMap, dmaap_name ); + } + + +} diff --git a/src/main/java/org/onap/dmaap/dbcapi/aaf/authentication/ApiPolicy.java b/src/main/java/org/onap/dmaap/dbcapi/aaf/authentication/ApiPolicy.java new file mode 100644 index 0000000..a86f83f --- /dev/null +++ b/src/main/java/org/onap/dmaap/dbcapi/aaf/authentication/ApiPolicy.java @@ -0,0 +1,58 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2017 AT&T 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.aaf.authentication; + +import org.onap.dmaap.dbcapi.aaf.DmaapPerm; +import org.onap.dmaap.dbcapi.logging.BaseLoggingClass; +import org.onap.dmaap.dbcapi.logging.DmaapbcLogMessageEnum; +import org.onap.dmaap.dbcapi.util.DmaapConfig; + +public class ApiPolicy extends BaseLoggingClass { + static String allow = "allow"; + String dClass = null; + ApiPermissionInterface perm = null; + + public ApiPolicy() { + DmaapConfig p = (DmaapConfig)DmaapConfig.getConfig(); + dClass = p.getProperty( "ApiPermission.Class", allow ); + logger.info( "ApiPolicy implements " + dClass); + if ( dClass.equalsIgnoreCase( allow )) { + return; + } + + try { + perm = (ApiPermissionInterface) (Class.forName(dClass).newInstance()); + } catch (Exception ee ) { + errorLogger.error(DmaapbcLogMessageEnum.UNEXPECTED_CONDITION, "attempting to instantiate " + dClass ); + errorLogger.error( "trace is: " + ee ); + } + } + + public void check( String mechid, String pwd, DmaapPerm p ) throws AuthenticationErrorException { + if ( dClass.equalsIgnoreCase( allow )) { + return; + } + + // execute check of loaded class + perm.check( mechid, pwd, p ); + + } + +} diff --git a/src/main/java/org/onap/dmaap/dbcapi/aaf/authentication/AuthenticationErrorException.java b/src/main/java/org/onap/dmaap/dbcapi/aaf/authentication/AuthenticationErrorException.java new file mode 100644 index 0000000..c740eac --- /dev/null +++ b/src/main/java/org/onap/dmaap/dbcapi/aaf/authentication/AuthenticationErrorException.java @@ -0,0 +1,29 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2017 AT&T 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.aaf.authentication; + +public class AuthenticationErrorException extends Exception { + /** + * + */ + private static final long serialVersionUID = 1L; + +} diff --git a/src/main/java/org/onap/dmaap/dbcapi/aaf/client/DrProvConnection.java b/src/main/java/org/onap/dmaap/dbcapi/aaf/client/DrProvConnection.java new file mode 100644 index 0000000..2d2ca8f --- /dev/null +++ b/src/main/java/org/onap/dmaap/dbcapi/aaf/client/DrProvConnection.java @@ -0,0 +1,797 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2017 AT&T 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.aaf.client; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.net.ConnectException; +import java.net.ProtocolException; +import java.net.SocketException; +import java.net.URL; +import java.util.ArrayList; + +import javax.net.ssl.HttpsURLConnection; + +import org.apache.log4j.Logger; +import org.apache.log4j.PropertyConfigurator; +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.DR_Pub; +import org.onap.dmaap.dbcapi.model.DR_Sub; +import org.onap.dmaap.dbcapi.model.Feed; +import org.onap.dmaap.dbcapi.service.DmaapService; +import org.onap.dmaap.dbcapi.util.RandomInteger; + + + +public class DrProvConnection extends BaseLoggingClass { + + + private String provURL; + + private HttpsURLConnection uc; + + + public DrProvConnection() { + provURL = new DmaapService().getDmaap().getDrProvUrl(); + if ( provURL.length() < 1 ) { + errorLogger.error( DmaapbcLogMessageEnum.PREREQ_DMAAP_OBJECT, "getDrProvUrl"); + } + + } + + public boolean makeFeedConnection() { + return makeConnection( provURL ); + } + public boolean makeFeedConnection(String feedId) { + return makeConnection( provURL + "/feed/" + feedId ); + } + public boolean makeSubPostConnection( String subURL ) { + String[] parts = subURL.split("/"); + String revisedURL = provURL + "/" + parts[3] + "/" + parts[4]; + logger.info( "mapping " + subURL + " to " + revisedURL ); + return makeConnection( revisedURL ); + } + public boolean makeSubPutConnection( String subId ) { + String revisedURL = provURL + "/subs/" + subId; + logger.info( "mapping " + subId + " to " + revisedURL ); + return makeConnection( revisedURL ); + } + + public boolean makeIngressConnection( String feed, String user, String subnet, String nodep ) { + String uri = String.format("/internal/route/ingress/?feed=%s&user=%s&subnet=%s&nodepatt=%s", + feed, user, subnet, nodep ); + return makeConnection( provURL + uri ); + } + public boolean makeEgressConnection( String sub, String nodep ) { + String uri = String.format("/internal/route/egress/?sub=%s&node=%s", + sub, nodep ); + return makeConnection( provURL + uri ); + } + public boolean makeNodesConnection( String varName ) { + + String uri = String.format("/internal/api/%s", varName); + return makeConnection( provURL + uri ); + } + + public boolean makeNodesConnection( String varName, String val ) { + + if ( val == null ) { + return false; + } + String cv = val.replaceAll("\\|", "%7C"); + String uri = String.format( "/internal/api/%s?val=%s", varName, cv ); + + return makeConnection( provURL + uri ); + } + + private boolean makeConnection( String pURL ) { + + try { + URL u = new URL( pURL ); + uc = (HttpsURLConnection) u.openConnection(); + uc.setInstanceFollowRedirects(false); + logger.info( "successful connect to " + pURL ); + return(true); + } catch (Exception e) { + errorLogger.error( DmaapbcLogMessageEnum.HTTP_CONNECTION_ERROR, pURL, e.getMessage() ); + e.printStackTrace(); + return(false); + } + + } + + private String bodyToString( InputStream is ) { + logger.info( "is=" + 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( DmaapbcLogMessageEnum.IO_EXCEPTION, ex.getMessage()); + } + + return sb.toString(); + } + + + public String doPostFeed( Feed postFeed, ApiError err ) { + + byte[] postData = postFeed.getBytes(); + logger.info( "post fields=" + postData.toString() ); + String responsemessage = null; + String responseBody = null; + + try { + logger.info( "uc=" + uc ); + uc.setRequestMethod("POST"); + uc.setRequestProperty("Content-Type", "application/vnd.att-dr.feed"); + uc.setRequestProperty( "charset", "utf-8"); + uc.setRequestProperty( "X-ATT-DR-ON-BEHALF-OF", postFeed.getOwner() ); + uc.setRequestProperty( "Content-Length", Integer.toString( postData.length )); + uc.setUseCaches(false); + uc.setDoOutput(true); + OutputStream os = null; + int rc = -1; + + try { + uc.connect(); + os = uc.getOutputStream(); + os.write( postData ); + + } 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) { + } + } + 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); + } + } + } + if (rc == 201 ) { + responseBody = bodyToString( uc.getInputStream() ); + logger.info( "responseBody=" + responseBody ); + + } else { + err.setCode( rc ); + err.setMessage(responsemessage); + } + + } catch (ConnectException ce) { + errorLogger.error(DmaapbcLogMessageEnum.HTTP_CONNECTION_EXCEPTION, provURL, ce.getMessage() ); + err.setCode( 500 ); + err.setMessage("Backend connection refused"); + } 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"); + } 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"); + } + } + finally { + try { + uc.disconnect(); + } catch ( Exception e ) {} + } + return responseBody; + + } + + + // the POST for /internal/route/ingress doesn't return any data, so needs a different function + // the POST for /internal/route/egress doesn't return any data, so needs a different function + public int doXgressPost( ApiError err ) { + + String responsemessage = null; + int rc = -1; + + try { + uc.setRequestMethod("POST"); +// uc.setRequestProperty("Content-Type", "application/vnd.att-dr.feed"); +// uc.setRequestProperty( "charset", "utf-8"); +// uc.setRequestProperty( "X-ATT-DR-ON-BEHALF-OF", postFeed.getOwner() ); +// uc.setRequestProperty( "Content-Length", Integer.toString( postData.length )); +// uc.setUseCaches(false); +// uc.setDoOutput(true); + OutputStream os = null; + + + try { + uc.connect(); + os = uc.getOutputStream(); + + + } 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) { + } + } + rc = uc.getResponseCode(); + logger.info( "http response code:" + rc ); + responsemessage = uc.getResponseMessage(); + logger.info( "responsemessage=" + responsemessage ); + + + + if (rc < 200 || rc >= 300 ) { + err.setCode( rc ); + err.setMessage(responsemessage); + } + } catch (Exception e) { + System.err.println("Unable to read response " ); + e.printStackTrace(); + } finally { + try { + uc.disconnect(); + } catch ( Exception e ) {} + } + + return rc; + + } + + public String doPostDr_Sub( DR_Sub postSub, ApiError err ) { + logger.info( "entry: doPostDr_Sub() " ); + byte[] postData = postSub.getBytes(); + logger.info( "post fields=" + postData ); + String responsemessage = null; + String responseBody = null; + + try { + + uc.setRequestMethod("POST"); + + uc.setRequestProperty("Content-Type", "application/vnd.att-dr.subscription"); + uc.setRequestProperty( "charset", "utf-8"); + uc.setRequestProperty( "X-ATT-DR-ON-BEHALF-OF", "DGL" ); + uc.setRequestProperty( "Content-Length", Integer.toString( postData.length )); + uc.setUseCaches(false); + uc.setDoOutput(true); + OutputStream os = null; + int rc = -1; + + try { + uc.connect(); + os = uc.getOutputStream(); + os.write( postData ); + + } 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) { + } + } + 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); + } + } + } + if (rc == 201 ) { + responseBody = bodyToString( uc.getInputStream() ); + logger.info( "responseBody=" + responseBody ); + + } else { + err.setCode(rc); + err.setMessage(responsemessage); + } + + } catch (Exception e) { + System.err.println("Unable to read response " ); + e.printStackTrace(); + } finally { + try { + uc.disconnect(); + } catch ( Exception e ) {} + } + return responseBody; + + } + + + public String doPutFeed(Feed putFeed, ApiError err) { + byte[] postData = putFeed.getBytes(); + logger.info( "post fields=" + postData.toString() ); + String responsemessage = null; + String responseBody = null; + + try { + logger.info( "uc=" + uc ); + uc.setRequestMethod("PUT"); + uc.setRequestProperty("Content-Type", "application/vnd.att-dr.feed"); + uc.setRequestProperty( "charset", "utf-8"); + uc.setRequestProperty( "X-ATT-DR-ON-BEHALF-OF", putFeed.getOwner() ); + uc.setRequestProperty( "Content-Length", Integer.toString( postData.length )); + uc.setUseCaches(false); + uc.setDoOutput(true); + OutputStream os = null; + int rc = -1; + + try { + uc.connect(); + os = uc.getOutputStream(); + os.write( postData ); + + } 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) { + } + } + 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); + } + } + } + if (rc >= 200 && rc < 300 ) { + responseBody = bodyToString( uc.getInputStream() ); + logger.info( "responseBody=" + responseBody ); + + } else if ( rc == 404 ) { + err.setCode( rc ); + err.setFields( "feedid"); + String message = "FeedId " + putFeed.getFeedId() + " not found on DR to update. Out-of-sync condition?"; + err.setMessage( message ); + errorLogger.error( DmaapbcLogMessageEnum.PROV_OUT_OF_SYNC, "Feed", putFeed.getFeedId() ); + + } else { + err.setCode( rc ); + err.setMessage(responsemessage); + } + + } catch (ConnectException ce) { + errorLogger.error( DmaapbcLogMessageEnum.HTTP_CONNECTION_EXCEPTION, provURL, ce.getMessage() ); + err.setCode( 500 ); + err.setMessage("Backend connection refused"); + } 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"); + } 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"); + } + } finally { + try { + uc.disconnect(); + } catch ( Exception e ) {} + } + return responseBody; + } + public String doPutDr_Sub(DR_Sub postSub, ApiError err) { + logger.info( "entry: doPutDr_Sub() " ); + byte[] postData = postSub.getBytes(); + logger.info( "post fields=" + postData ); + String responsemessage = null; + String responseBody = null; + + try { + + uc.setRequestMethod("PUT"); + + uc.setRequestProperty("Content-Type", "application/vnd.att-dr.subscription"); + uc.setRequestProperty( "charset", "utf-8"); + uc.setRequestProperty( "X-ATT-DR-ON-BEHALF-OF", "DGL" ); + uc.setRequestProperty( "Content-Length", Integer.toString( postData.length )); + uc.setUseCaches(false); + uc.setDoOutput(true); + OutputStream os = null; + int rc = -1; + + try { + uc.connect(); + os = uc.getOutputStream(); + os.write( postData ); + + } 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) { + } + } + 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); + } + } + } + if (rc == 200 ) { + responseBody = bodyToString( uc.getInputStream() ); + logger.info( "responseBody=" + responseBody ); + + } else { + err.setCode(rc); + err.setMessage(responsemessage); + } + + } catch (ConnectException ce) { + 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(); + } finally { + uc.disconnect(); + } + return responseBody; + + } + + public String doGetNodes( ApiError err ) { + logger.info( "entry: doGetNodes() " ); + //byte[] postData = postSub.getBytes(); + //logger.info( "get fields=" + postData ); + String responsemessage = null; + String responseBody = null; + + try { + + uc.setRequestMethod("GET"); + + //uc.setRequestProperty("Content-Type", "application/vnd.att-dr.subscription"); + //uc.setRequestProperty( "charset", "utf-8"); + //uc.setRequestProperty( "X-ATT-DR-ON-BEHALF-OF", "DGL" ); + //uc.setRequestProperty( "Content-Length", Integer.toString( postData.length )); + //uc.setUseCaches(false); + //uc.setDoOutput(true); + OutputStream os = null; + int rc = -1; + + try { + uc.connect(); + //os = uc.getOutputStream(); + //os.write( postData ); + + } 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) { + } + } + 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) { + 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(); + } finally { + uc.disconnect(); + } + return responseBody; + + } + public String doPutNodes( ApiError err ) { + logger.info( "entry: doPutNodes() " ); + //byte[] postData = nodeList.getBytes(); + //logger.info( "get fields=" + postData ); + String responsemessage = null; + String responseBody = null; + + try { + + uc.setRequestMethod("PUT"); + + //uc.setRequestProperty("Content-Type", "application/vnd.att-dr.subscription"); + //uc.setRequestProperty( "charset", "utf-8"); + //uc.setRequestProperty( "X-ATT-DR-ON-BEHALF-OF", "DGL" ); + //uc.setRequestProperty( "Content-Length", Integer.toString( postData.length )); + uc.setUseCaches(false); + //uc.setDoOutput(true); + OutputStream os = null; + int rc = -1; + + try { + uc.connect(); + //os = uc.getOutputStream(); + //os.write( postData ); + + } 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) { + } + } + 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); + if (rc == 200 ) { + responseBody = bodyToString( uc.getInputStream() ); + logger.info( "responseBody=" + responseBody ); + + } else { + + err.setMessage(responsemessage); + } + + } catch (Exception e) { + System.err.println("Unable to read response " ); + e.printStackTrace(); + } finally { + uc.disconnect(); + } + return responseBody; + + } + + public String doDeleteFeed(Feed putFeed, ApiError err) { + //byte[] postData = putFeed.getBytes(); + //logger.info( "post fields=" + postData.toString() ); + String responsemessage = null; + String responseBody = null; + + try { + logger.info( "uc=" + uc ); + uc.setRequestMethod("DELETE"); + uc.setRequestProperty("Content-Type", "application/vnd.att-dr.feed"); + uc.setRequestProperty( "charset", "utf-8"); + uc.setRequestProperty( "X-ATT-DR-ON-BEHALF-OF", putFeed.getOwner() ); + //uc.setRequestProperty( "Content-Length", Integer.toString( postData.length )); + uc.setUseCaches(false); + uc.setDoOutput(true); + OutputStream os = null; + int rc = -1; + + try { + uc.connect(); + os = uc.getOutputStream(); + //os.write( postData ); + + } 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) { + } + } + 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); + } + } + } + if (rc >= 200 && rc < 300 ) { + responseBody = bodyToString( uc.getInputStream() ); + logger.info( "responseBody=" + responseBody ); + + } else if ( rc == 404 ) { + err.setCode( rc ); + err.setFields( "feedid"); + String message = "FeedId " + putFeed.getFeedId() + " not found on DR to update. Out-of-sync condition?"; + err.setMessage( message ); + errorLogger.error( DmaapbcLogMessageEnum.PROV_OUT_OF_SYNC, "Feed", putFeed.getFeedId() ); + + } else { + err.setCode( rc ); + err.setMessage(responsemessage); + } + + } catch (ConnectException ce) { + errorLogger.error( DmaapbcLogMessageEnum.HTTP_CONNECTION_EXCEPTION, provURL, ce.getMessage() ); + err.setCode( 500 ); + err.setMessage("Backend connection refused"); + } 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"); + } 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"); + } + } finally { + try { + uc.disconnect(); + } catch ( Exception e ) {} + } + 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); + } + + } + */ + + +} diff --git a/src/main/java/org/onap/dmaap/dbcapi/aaf/client/MrProvConnection.java b/src/main/java/org/onap/dmaap/dbcapi/aaf/client/MrProvConnection.java new file mode 100644 index 0000000..420f10e --- /dev/null +++ b/src/main/java/org/onap/dmaap/dbcapi/aaf/client/MrProvConnection.java @@ -0,0 +1,218 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2017 AT&T 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.aaf.client; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.net.ConnectException; +import java.net.ProtocolException; +import java.net.URL; +import java.net.UnknownHostException; + +import javax.net.ssl.HttpsURLConnection; + +import org.apache.commons.codec.binary.Base64; +import org.apache.log4j.Logger; +import org.onap.dmaap.dbcapi.aaf.AafDecrypt; +import org.onap.dmaap.dbcapi.aaf.AafService; +import org.onap.dmaap.dbcapi.aaf.DecryptionInterface; +import org.onap.dmaap.dbcapi.aaf.AafService.ServiceType; +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.MR_Cluster; +import org.onap.dmaap.dbcapi.model.Topic; +import org.onap.dmaap.dbcapi.util.DmaapConfig; + +public class MrProvConnection extends BaseLoggingClass{ + + private String provURL; + + private HttpsURLConnection uc; + + + private String topicMgrCred; + + private String getCred( ) { + String mechIdProperty = "aaf.TopicMgrUser"; + String pwdProperty = "aaf.TopicMgrPassword"; + DmaapConfig p = (DmaapConfig)DmaapConfig.getConfig(); + + String user = p.getProperty( mechIdProperty, "noMechId@domain.netset.com" ); + + String pwd = ""; + String encPwd = p.getProperty( pwdProperty, "notSet" ); + + AafDecrypt decryptor = new AafDecrypt(); + pwd = decryptor.decrypt(encPwd); + + return user + ":" + pwd; + + + + } + + + public MrProvConnection( ) { + topicMgrCred = getCred(); + + } + + public boolean makeTopicConnection( MR_Cluster cluster ) { + logger.info( "connect to cluster: " + cluster.getDcaeLocationName()); + + + provURL = cluster.getTopicProtocol() + "://" + cluster.getFqdn() + ":" + cluster.getTopicPort() + "/topics/create"; + + return makeConnection( provURL ); + } + + private boolean makeConnection( 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); + } catch (Exception e) { + logger.error("Unexpected error during openConnection of " + pURL ); + e.printStackTrace(); + 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()); + + + String responsemessage = null; + int rc = -1; + + + try { + byte[] postData = postTopic.getBytes(); + logger.info( "post fields=" + postData.toString() ); + uc.setRequestProperty("Authorization", auth); + logger.info( "Authenticating with " + auth ); + 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 { + uc.connect(); + os = uc.getOutputStream(); + os.write( postData ); + + } 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) { + } + } 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()); + }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()); + } + rc = uc.getResponseCode(); + logger.info( "http response code:" + rc ); + err.setCode(rc); + responsemessage = uc.getResponseMessage(); + logger.info( "responsemessage=" + responsemessage ); + err.setMessage(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); + } + } + } + if (rc >= 200 && rc < 300 ) { + String responseBody = null; + responseBody = bodyToString( uc.getInputStream() ); + logger.info( "responseBody=" + responseBody ); + return responseBody; + + } + + } catch (Exception e) { + System.err.println("Unable to read response " ); + e.printStackTrace(); + } + finally { + try { + uc.disconnect(); + } catch ( Exception e ) {} + } + return new String( rc +": " + responsemessage ); + + } + + + + +} diff --git a/src/main/java/org/onap/dmaap/dbcapi/aaf/client/MrTopicConnection.java b/src/main/java/org/onap/dmaap/dbcapi/aaf/client/MrTopicConnection.java new file mode 100644 index 0000000..0b49379 --- /dev/null +++ b/src/main/java/org/onap/dmaap/dbcapi/aaf/client/MrTopicConnection.java @@ -0,0 +1,176 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2017 AT&T 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.aaf.client; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.net.ProtocolException; +import java.net.URL; + +import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.SSLException; + +import org.apache.commons.codec.binary.Base64; +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.MR_Cluster; + +public class MrTopicConnection extends BaseLoggingClass { + private String topicURL; + + private HttpsURLConnection uc; + + + private String mmProvCred; + + + + public MrTopicConnection(String user, String pwd ) { + mmProvCred = new String( user + ":" + pwd ); + + } + + public boolean makeTopicConnection( MR_Cluster cluster, String topic, String overrideFqdn ) { + String fqdn = overrideFqdn != null ? overrideFqdn : cluster.getFqdn(); + logger.info( "connect to cluster: " + fqdn + " for topic: " + topic ); + + + topicURL = cluster.getTopicProtocol() + "://" + fqdn + ":" + cluster.getTopicPort() + "/events/" + topic ; + + return makeConnection( topicURL ); + } + + private boolean makeConnection( String pURL ) { + logger.info( "makeConnection to " + pURL ); + + try { + URL u = new URL( pURL ); + uc = (HttpsURLConnection) u.openConnection(); + uc.setInstanceFollowRedirects(false); + logger.info( "open connection to " + pURL ); + return(true); + } catch (Exception e) { + logger.error("Unexpected error during openConnection of " + pURL ); + e.printStackTrace(); + 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 ApiError doPostMessage( String postMessage ) { + ApiError response = new ApiError(); + String auth = "Basic " + Base64.encodeBase64String(mmProvCred.getBytes()); + + + + try { + byte[] postData = postMessage.getBytes(); + logger.info( "post fields=" + postMessage ); + uc.setRequestProperty("Authorization", auth); + logger.info( "Authenticating with " + auth ); + 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 { + uc.connect(); + os = uc.getOutputStream(); + os.write( postData ); + + } 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) { + } + } catch ( SSLException se ) { + response.setCode(500); + response.setMessage( se.getMessage()); + return response; + + } + response.setCode( uc.getResponseCode()); + logger.info( "http response code:" + response.getCode()); + response.setMessage( uc.getResponseMessage() ); + logger.info( "response message=" + response.getMessage() ); + + + if ( response.getMessage() == 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) { + response.setMessage( h0.substring(j + 1) ); + } + } + } + if ( response.is2xx() ) { + response.setFields( bodyToString( uc.getInputStream() ) ); + logger.info( "responseBody=" + response.getFields() ); + return response; + + } + + } catch (Exception e) { + response.setCode(500); + response.setMessage( "Unable to read response"); + logger.warn( response.getMessage() ); + e.printStackTrace(); + } + finally { + try { + uc.disconnect(); + } catch ( Exception e ) {} + } + return response; + + } + +} diff --git a/src/main/java/org/onap/dmaap/dbcapi/aaf/database/ConnWrapper.java b/src/main/java/org/onap/dmaap/dbcapi/aaf/database/ConnWrapper.java new file mode 100644 index 0000000..019caef --- /dev/null +++ b/src/main/java/org/onap/dmaap/dbcapi/aaf/database/ConnWrapper.java @@ -0,0 +1,63 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2017 AT&T 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.aaf.database; + +import java.sql.*; + + +public abstract class ConnWrapper<T, U> { + protected Connection c; + protected PreparedStatement ps; + protected ResultSet rs; + protected abstract T run(U u) throws Exception; + public T protect(ConnectionFactory cf, U u) throws DBException { + try { + try { + return(attempt(cf, u, false)); + } catch (SQLException sqle) { + return(attempt(cf, u, true)); + } + } catch (RuntimeException rte) { + throw rte; + } catch (Exception e) { + throw new DBException(e); + } + } + private T attempt(ConnectionFactory cf, U u, boolean fresh) throws Exception { + c = null; + ps = null; + rs = null; + try { + c = cf.get(fresh); + T ret = run(u); + cf.release(c); + c = null; + return(ret); + } finally { + if (rs != null) { try { rs.close(); } catch (Exception e) {}} + rs = null; + if (ps != null) { try { ps.close(); } catch (Exception e) {}} + ps = null; + if (c != null) { try { c.close(); } catch (Exception e) {}} + c = null; + } + } +} diff --git a/src/main/java/org/onap/dmaap/dbcapi/aaf/database/ConnectionFactory.java b/src/main/java/org/onap/dmaap/dbcapi/aaf/database/ConnectionFactory.java new file mode 100644 index 0000000..64a2959 --- /dev/null +++ b/src/main/java/org/onap/dmaap/dbcapi/aaf/database/ConnectionFactory.java @@ -0,0 +1,89 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2017 AT&T 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.aaf.database; + +import java.sql.*; +import java.util.*; + +import org.apache.log4j.Logger; + +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; + +import org.onap.dmaap.dbcapi.logging.DmaapbcLogMessageEnum; +import org.onap.dmaap.dbcapi.util.DmaapConfig; + +public class ConnectionFactory { + static final EELFLogger logger = EELFManager.getInstance().getLogger( ConnectionFactory.class ); + static final EELFLogger appLogger = EELFManager.getInstance().getApplicationLogger(); + static final EELFLogger auditLogger = EELFManager.getInstance().getAuditLogger(); + static final EELFLogger debugLogger = EELFManager.getInstance().getDebugLogger(); + static final EELFLogger errorLogger = EELFManager.getInstance().getErrorLogger(); + static final EELFLogger metricsLogger = EELFManager.getInstance().getMetricsLogger(); + static final EELFLogger serverLogger = EELFManager.getInstance().getServerLogger(); + + static { + try { + Class.forName("org.postgresql.Driver"); + } catch (Exception e) { + logger.error("Unable to load postgres driver " + e, e); + } + } + private static ConnectionFactory instance = new ConnectionFactory(); + private String host; + private String dbname; + private String dbuser; + private String dbcr; + public ConnectionFactory() { + Properties p = DmaapConfig.getConfig(); + host = p.getProperty("DB.host", "dcae-pstg-write-ftl.domain.notset.com"); + dbname = p.getProperty("DB.name", "dmaap"); + dbuser = p.getProperty("DB.user", "dmaap_admin"); + dbcr = p.getProperty("DB.cred", "test234-ftl"); + } + public static ConnectionFactory getDefaultInstance() { + return(instance); + } + private Connection[] pool = new Connection[5]; + private int cur; + public Connection get(boolean fresh) throws SQLException { + if (!fresh) { + synchronized(this) { + if (cur > 0) { + return(pool[--cur]); + } + } + } + Properties p = new Properties(); + p.put("user", dbuser); + p.put("password", dbcr); + return(DriverManager.getConnection("jdbc:postgresql://" + host + "/" + dbname, p)); + } + public void release(Connection c) { + synchronized(this) { + if (cur < pool.length) { + pool[cur++] = c; + return; + } + } + try { c.close(); } catch (Exception e) {} + } +} diff --git a/src/main/java/org/onap/dmaap/dbcapi/aaf/database/DBException.java b/src/main/java/org/onap/dmaap/dbcapi/aaf/database/DBException.java new file mode 100644 index 0000000..f73e510 --- /dev/null +++ b/src/main/java/org/onap/dmaap/dbcapi/aaf/database/DBException.java @@ -0,0 +1,34 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2017 AT&T 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.aaf.database; + +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; + +import org.onap.dmaap.dbcapi.logging.DmaapbcLogMessageEnum; + +public class DBException extends RuntimeException { + static final EELFLogger errorLogger = EELFManager.getInstance().getErrorLogger(); + public DBException(Exception e) { + super(e); + errorLogger.error(DmaapbcLogMessageEnum.DB_ACCESS_ERROR, e.getMessage()); + } +} diff --git a/src/main/java/org/onap/dmaap/dbcapi/aaf/database/DBFieldHandler.java b/src/main/java/org/onap/dmaap/dbcapi/aaf/database/DBFieldHandler.java new file mode 100644 index 0000000..52af453 --- /dev/null +++ b/src/main/java/org/onap/dmaap/dbcapi/aaf/database/DBFieldHandler.java @@ -0,0 +1,202 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2017 AT&T 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.aaf.database; + +import java.lang.reflect.*; +import java.sql.*; +import java.util.*; + +import org.apache.log4j.Logger; + +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; + +import org.onap.dmaap.dbcapi.logging.DmaapbcLogMessageEnum; + + +public class DBFieldHandler { + static final EELFLogger errorLogger = EELFManager.getInstance().getErrorLogger(); + + public static interface SqlOp { + public Object get(ResultSet rs, int index) throws Exception; + public void set(PreparedStatement ps, int index, Object value) throws Exception; + } + private static class AofString implements SqlOp { + public Object get(ResultSet rs, int index) throws Exception { + String val = rs.getString(index); + if (val == null) { + return(null); + } + String[] ret = val.split(","); + for (int i = 0; i < ret.length; i++) { + ret[i] = funesc(ret[i]); + } + return(ret); + } + public void set(PreparedStatement ps, int index, Object x) throws Exception { + String[] val = (String[])x; + if (val == null) { + ps.setString(index, null); + return; + } + StringBuffer sb = new StringBuffer(); + String sep = ""; + for (String s: val) { + sb.append(sep).append(fesc(s)); + sep = ","; + } + ps.setString(index, sb.toString()); + } + } + private static class EnumSql implements SqlOp { + private Class enclass; + public EnumSql(Class enclass) { + this.enclass = enclass; + } + @SuppressWarnings("unchecked") + public Object get(ResultSet rs, int index) throws Exception { + String val = rs.getString(index); + if (val == null) { + return(null); + } else { + return(Enum.valueOf(enclass, val)); + } + } + public void set(PreparedStatement ps, int index, Object value) throws Exception { + if (value == null) { + ps.setString(index, null); + } else { + ps.setString(index, value.toString()); + } + } + } + private static class SqlDate implements SqlOp { + public Object get(ResultSet rs, int index) throws Exception { + return(rs.getTimestamp(index)); + } + public void set(PreparedStatement ps, int index, Object val) throws Exception { + if (val instanceof java.util.Date && !(val instanceof java.sql.Timestamp)) { + val = new java.sql.Timestamp(((java.util.Date)val).getTime()); + } + ps.setTimestamp(index, (java.sql.Timestamp)val); + } + } + private static class SqlType implements SqlOp { + private Method sqlget; + private Method sqlset; + private SqlType(String tag) throws Exception { + sqlget = ResultSet.class.getMethod("get" + tag, Integer.TYPE); + sqlset = PreparedStatement.class.getMethod("set" + tag, Integer.TYPE, sqlget.getReturnType()); + sqltypes.put(sqlget.getReturnType().getName(), this); + } + public Object get(ResultSet rs, int index) throws Exception { + return(sqlget.invoke(rs, index)); + } + public void set(PreparedStatement ps, int index, Object val) throws Exception { + try { + sqlset.invoke(ps, index, val); + } catch (Exception e) { + errorLogger.error(DmaapbcLogMessageEnum.DB_FIELD_INIT_ERROR, Integer.toString(index), val.toString(), ps.toString()); + throw e; + } + } + } + private static Map<String, SqlOp> sqltypes; + static { + sqltypes = new HashMap<String, SqlOp>(); + sqltypes.put("[Ljava.lang.String;", new AofString()); + sqltypes.put("java.util.Date", new SqlDate()); + try { + new SqlType("Boolean"); + new SqlType("Timestamp"); + new SqlType("Double"); + new SqlType("Float"); + new SqlType("Int"); + new SqlType("Long"); + new SqlType("Short"); + new SqlType("String"); + } catch (Exception e) { + errorLogger.error(DmaapbcLogMessageEnum.DB_ACCESS_INIT_ERROR, e.getMessage() ); + } + } + private Method objget; + private Method objset; + private SqlOp sqlop; + private int fieldnum; + public void copy(Object from, Object to) throws Exception { + objset.invoke(to, objget.invoke(from)); + } + public void setKey(Object o, String key) throws Exception { + objset.invoke(o, key); + } + public String getKey(Object o) throws Exception { + return((String)objget.invoke(o)); + } + public void toSQL(Object o, PreparedStatement ps) throws Exception { + sqlop.set(ps, fieldnum, objget.invoke(o)); + } + public void fromSQL(ResultSet r, Object o) throws Exception { + objset.invoke(o, sqlop.get(r, fieldnum)); + } + public DBFieldHandler(Class<?> c, String fieldname, int fieldnum) throws Exception { + this(c, fieldname, fieldnum, null); + } + public DBFieldHandler(Class<?> c, String fieldname, int fieldnum, SqlOp op) throws Exception { + this.fieldnum = fieldnum; + StringBuffer sb = new StringBuffer(); + for (String s: fieldname.split("_")) { + sb.append(s.substring(0, 1).toUpperCase()).append(s.substring(1)); + } + String camelcase = sb.toString(); + try { + objget = c.getMethod("is" + camelcase); + } catch (Exception e) { + objget = c.getMethod("get" + camelcase); + } + objset = c.getMethod("set" + camelcase, objget.getReturnType()); + sqlop = op; + if (sqlop != null) { + return; + } + Class<?> x = objget.getReturnType(); + if (x.isEnum()) { + sqlop = new EnumSql(x); + return; + } + sqlop = sqltypes.get(x.getName()); + if (sqlop != null) { + return; + } + errorLogger.error(DmaapbcLogMessageEnum.DB_NO_FIELD_HANDLER, c.getName(), fieldname, Integer.toString(fieldnum), x.getName()); + } + public static String fesc(String s) { + if (s == null) { + return(s); + } + return(s.replaceAll("@", "@a").replaceAll(";", "@s").replaceAll(",", "@c")); + } + public static String funesc(String s) { + if (s == null) { + return(s); + } + return(s.replaceAll("@c", ",").replaceAll("@s", ";").replaceAll("@a", "@")); + } +} diff --git a/src/main/java/org/onap/dmaap/dbcapi/aaf/database/DBMap.java b/src/main/java/org/onap/dmaap/dbcapi/aaf/database/DBMap.java new file mode 100644 index 0000000..8b8e3ad --- /dev/null +++ b/src/main/java/org/onap/dmaap/dbcapi/aaf/database/DBMap.java @@ -0,0 +1,138 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2017 AT&T 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.aaf.database; + +import java.sql.*; +import java.util.*; + +public class DBMap<C> extends TableHandler<C> implements Map<String, C> { + public DBMap(Class<C> cls, String tabname, String keyfield) throws Exception { + this(ConnectionFactory.getDefaultInstance(), cls, tabname, keyfield); + } + public DBMap(ConnectionFactory cf, Class<C> cls, String tabname, String keyfield) throws Exception { + super(cf, cls, tabname, keyfield); + } + public void clear() throws UnsupportedOperationException { + throw new UnsupportedOperationException(); + } + public boolean containsKey(Object key) throws DBException { + return(get(key) != null); + } + public boolean containsValue(Object value) throws UnsupportedOperationException { + throw new UnsupportedOperationException(); + } + public boolean isEmpty() { + return(false); + } + public Set<Map.Entry<String, C>> entrySet() throws DBException { + return(list()); + } + public Set<String> keySet() throws DBException { + Set<String> ret = new HashSet<String>(); + for (Map.Entry<String, C> x: list()) { + ret.add(x.getKey()); + } + return(ret); + } + public void putAll(Map<? extends String, ? extends C> m) throws UnsupportedOperationException { + throw new UnsupportedOperationException(); + } + public int size() { + return(2); + } + public Collection<C> values() throws DBException { + Collection<C> ret = new Vector<C>(); + for (Map.Entry<String, C> x: list()) { + ret.add(x.getValue()); + } + return(ret); + } + public C get(Object key) throws DBException { + if (!(key instanceof String)) { + return(null); + } + return((new ConnWrapper<C, String>() { + protected C run(String key) throws Exception { + ps = c.prepareStatement(getstmt); + ps.setString(1, (String)key); + rs = ps.executeQuery(); + if (!rs.next()) { + return(null); + } + C ret = cls.newInstance(); + for (DBFieldHandler f: fields) { + f.fromSQL(rs, ret); + } + return(ret); + } + }).protect(cf, (String)key)); + } + public Set<Map.Entry<String, C>> list() throws DBException { + return((new ConnWrapper<Set<Map.Entry<String, C>>, Object>() { + protected Set<Map.Entry<String, C>> run(Object junk) throws Exception { + DBFieldHandler keyfield = fields[fields.length - 1]; + ps = c.prepareStatement(liststmt); + rs = ps.executeQuery(); + Set<Map.Entry<String, C>> ret = new HashSet<Map.Entry<String, C>>(); + while (rs.next()) { + C val = cls.newInstance(); + for (DBFieldHandler f: fields) { + f.fromSQL(rs, val); + } + String key = keyfield.getKey(val); + ret.add(new AbstractMap.SimpleEntry<String, C>(key, val)); + } + return(ret); + } + }).protect(cf, null)); + } + public C put(String key, C val) throws DBException { + try { + fields[fields.length - 1].setKey(val, key); + } 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); + for (DBFieldHandler f: fields) { + f.toSQL(val, ps); + } + ps.executeUpdate(); + return(null); + } + }).protect(cf, val)); + } + public C remove(Object key) throws DBException { + if (!(key instanceof String)) { + return(null); + } + return((new ConnWrapper<C, String>() { + protected C run(String key) throws Exception { + ps = c.prepareStatement(delstmt); + ps.setString(1, key); + ps.executeUpdate(); + return(null); + } + }).protect(cf, (String)key)); + } +} diff --git a/src/main/java/org/onap/dmaap/dbcapi/aaf/database/DBSingleton.java b/src/main/java/org/onap/dmaap/dbcapi/aaf/database/DBSingleton.java new file mode 100644 index 0000000..8c158ca --- /dev/null +++ b/src/main/java/org/onap/dmaap/dbcapi/aaf/database/DBSingleton.java @@ -0,0 +1,98 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2017 AT&T 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.aaf.database; + +import java.sql.*; +import java.util.*; + +import org.onap.dmaap.dbcapi.util.Singleton; + +public class DBSingleton<C> extends TableHandler<C> implements Singleton<C> { + private C singleton; + public DBSingleton(Class<C> cls, String tabname) throws Exception { + this(ConnectionFactory.getDefaultInstance(), cls, tabname); + } + public DBSingleton(ConnectionFactory cf, Class<C> cls, String tabname) throws Exception { + super(cf, cls, tabname, null); + singleton = cls.newInstance(); + } + public C get() throws DBException { + return((new ConnWrapper<C, Object>() { + protected C run(Object junk) throws Exception { + ps = c.prepareStatement(getstmt); + rs = ps.executeQuery(); + if (!rs.next()) { + return(null); + } + for (DBFieldHandler f: fields) { + f.fromSQL(rs, singleton); + } + return(singleton); + } + }).protect(cf, null)); + } + public void init(C val) throws DBException { + if (get() != null) { + return; + } + (new ConnWrapper<Void, C>() { + protected Void run(C val) throws Exception { + ps = c.prepareStatement(initstmt); + for (DBFieldHandler f: fields) { + f.toSQL(val, ps); + } + ps.executeUpdate(); + if (val != singleton) { + for (DBFieldHandler f: fields) { + f.copy(val, singleton); + } + } + return(null); + } + }).protect(cf, val); + } + public void update(C val) throws DBException { + (new ConnWrapper<Void, C>() { + protected Void run(C val) throws Exception { + ps = c.prepareStatement(insorreplstmt); + for (DBFieldHandler f: fields) { + f.toSQL(val, ps); + } + ps.executeUpdate(); + if (val != singleton) { + for (DBFieldHandler f: fields) { + f.copy(val, singleton); + } + } + return(null); + } + }).protect(cf, val); + } + public void remove() throws DBException { + (new ConnWrapper<Void, Object>() { + protected Void run(Object junk) throws Exception { + ps = c.prepareStatement(delstmt); + ps.executeUpdate(); + return(null); + } + }).protect(cf, null); + } +} diff --git a/src/main/java/org/onap/dmaap/dbcapi/aaf/database/DatabaseClass.java b/src/main/java/org/onap/dmaap/dbcapi/aaf/database/DatabaseClass.java new file mode 100644 index 0000000..baa86a6 --- /dev/null +++ b/src/main/java/org/onap/dmaap/dbcapi/aaf/database/DatabaseClass.java @@ -0,0 +1,270 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2017 AT&T 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.aaf.database; + +import java.util.*; +import java.sql.*; + +import org.onap.dmaap.dbcapi.logging.BaseLoggingClass; +import org.onap.dmaap.dbcapi.logging.DmaapbcLogMessageEnum; +import org.onap.dmaap.dbcapi.model.*; +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; + + private static long lastTime = 0L; + + private static class MirrorVectorHandler implements DBFieldHandler.SqlOp { + public Object get(ResultSet rs, int index) throws Exception { + String val = rs.getString(index); + if (val == null) { + return(null); + } + Set<ReplicationVector> rv = new HashSet<ReplicationVector>(); + for (String s: val.split(",")) { + String[] f = s.split(";"); + if (f.length < 3) { + continue; + } + rv.add(new ReplicationVector(DBFieldHandler.funesc(f[0]), DBFieldHandler.funesc(f[1]), DBFieldHandler.funesc(f[2]))); + } + return(rv); + } + public void set(PreparedStatement ps, int index, Object val) throws Exception { + if (val == null) { + ps.setString(index, null); + return; + } + Set xv = (Set)val; + StringBuffer sb = new StringBuffer(); + String sep = ""; + for (Object o: xv) { + ReplicationVector rv = (ReplicationVector)o; + sb.append(sep).append(DBFieldHandler.fesc(rv.getFqtn())).append(';').append(DBFieldHandler.fesc(rv.getSourceCluster())).append(';').append(DBFieldHandler.fesc(rv.getTargetCluster())); + sep = ","; + } + ps.setString(index, sb.toString()); + } + } + + // modified version of MirrorVectorHandler for Topics + 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<String>(); + for (String s: val.split(",")) { + //String[] f = s.split(";"); + //if (f.length < 3) { + // continue; + //} + 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; + StringBuffer sb = new StringBuffer(); + 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>(Dmaap.class, "dmaap"); + dcaeLocations = new DBMap<DcaeLocation>(DcaeLocation.class, "dcae_location", "dcae_location_name"); + dr_nodes = new DBMap<DR_Node>(DR_Node.class, "dr_node", "fqdn"); + dr_pubs = new DBMap<DR_Pub>(DR_Pub.class, "dr_pub", "pub_id"); + dr_subs = new DBMap<DR_Sub>(DR_Sub.class, "dr_sub", "sub_id"); + mr_clients = new DBMap<MR_Client>(MR_Client.class, "mr_client", "mr_client_id"); + mr_clusters = new DBMap<MR_Cluster>(MR_Cluster.class, "mr_cluster", "dcae_location_name"); + feeds = new DBMap<Feed>(Feed.class, "feed", "feed_id"); + TableHandler.setSpecialCase("topic", "replication_case", new TopicReplicationTypeHandler()); + topics = new DBMap<Topic>(Topic.class, "topic", "fqtn"); + //TableHandler.setSpecialCase("mirror_maker", "vectors", new MirrorVectorHandler()); + TableHandler.setSpecialCase("mirror_maker", "topics", new MirrorTopicsHandler()); + mirrors = new DBMap<MirrorMaker>(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<String, DcaeLocation>(); + dr_nodes = new HashMap<String, DR_Node>(); + dr_pubs = new HashMap<String, DR_Pub>(); + dr_subs = new HashMap<String, DR_Sub>(); + mr_clients = new HashMap<String, MR_Client>(); + mr_clusters = new HashMap<String, MR_Cluster>(); + feeds = new HashMap<String, Feed>(); + topics = new HashMap<String, Topic>(); + mirrors = new HashMap<String, MirrorMaker>(); + } + dmaap.init(new Dmaap("0", "", "", "", "", "", "", "")); + // check for, and set up initial data, if it isn't already there + Dmaap dmx = dmaap.get(); + if ("0".equals(dmx.getVersion())) { + + dmx = new Dmaap("0", "", "", "", "", "", "", ""); + dmx.setDmaapName(p.getProperty("DmaapName")); + dmx.setDrProvUrl("https://" + p.getProperty("DR.provhost", "notSet")); + dmx.setTopicNsRoot(p.getProperty("topicNsRoot")); + dmx.setBridgeAdminTopic("DCAE_MM_AGENT"); + + dmaap.update(dmx); + } + } catch (Exception e) { + errorLogger.error(DmaapbcLogMessageEnum.DB_UPDATE_ERROR, e.getMessage()); + } + } + + public synchronized static String getNextClientId() { + + long id = System.currentTimeMillis(); + if ( id <= lastTime ) { + id = lastTime + 1; + } + lastTime = id; + return Long.toString(id); + } + + + + +} diff --git a/src/main/java/org/onap/dmaap/dbcapi/aaf/database/LoadSchema.java b/src/main/java/org/onap/dmaap/dbcapi/aaf/database/LoadSchema.java new file mode 100644 index 0000000..bbd6f18 --- /dev/null +++ b/src/main/java/org/onap/dmaap/dbcapi/aaf/database/LoadSchema.java @@ -0,0 +1,117 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2017 AT&T 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.aaf.database; + +import java.io.*; +import java.sql.*; + +import org.apache.log4j.Logger; + +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; + +import org.onap.dmaap.dbcapi.logging.DmaapbcLogMessageEnum; + +public class LoadSchema { + private static final EELFLogger logger = EELFManager.getInstance().getLogger(LoadSchema.class); + private static final EELFLogger appLogger = EELFManager.getInstance().getApplicationLogger(); + private static final EELFLogger auditLogger = EELFManager.getInstance().getAuditLogger(); + private static final EELFLogger debugLogger = EELFManager.getInstance().getDebugLogger(); + private static final EELFLogger errorLogger = EELFManager.getInstance().getErrorLogger(); + private static final EELFLogger metricsLogger = EELFManager.getInstance().getMetricsLogger(); + + static int getVer(Statement s) throws SQLException { + ResultSet rs = null; + try { + rs = s.executeQuery("SELECT version FROM dmaapbc_sch_ver"); + rs.next(); + return(rs.getInt(1)); + } finally { + if (rs != null) { + rs.close(); + } + } + } + static void upgrade() throws SQLException { + ConnectionFactory cf = ConnectionFactory.getDefaultInstance(); + Connection c = null; + Statement stmt = null; + InputStream is = null; + try { + c = cf.get(true); + stmt = c.createStatement(); + int newver = -1; + try { + newver = getVer(stmt); + } catch (Exception e) {} + logger.info("Database schema currently at version " + newver++); + while ((is = LoadSchema.class.getClassLoader().getResourceAsStream("schema_" + newver + ".sql")) != null) { + logger.info("Upgrading database schema to version " + newver); + BufferedReader br = new BufferedReader(new InputStreamReader(is)); + String s; + String sofar = null; + while ((s = br.readLine()) != null) { + logger.info("SCHEMA: " + s); + s = s.trim(); + if (s.length() == 0 || s.startsWith("--")) { + continue; + } + if (sofar == null) { + sofar = s; + } else { + sofar = sofar + " " + s; + } + if (s.endsWith(";")) { + sofar = sofar.substring(0, sofar.length() - 1); + boolean ignore = false; + if (sofar.startsWith("@")) { + ignore = true; + sofar = sofar.substring(1).trim(); + } + try { + stmt.execute(sofar); + } catch (SQLException sqle) { + if (!ignore) { + throw sqle; + } + } + sofar = null; + } + } + is.close(); + is = null; + if (getVer(stmt) != newver) { + throw new SQLException("Schema version not properly updated to " + newver + " by upgrade script"); + } + logger.info("Upgrade to database schema version " + newver + " successful"); + newver++; + } + } catch (IOException ioe) { + throw new SQLException(ioe); + } finally { + if (stmt != null) { try { stmt.close(); } catch (Exception e) {}} + if (c != null) { try { c.close(); } catch (Exception e) {}} + } + } + public static void main(String[] args) throws Exception { + upgrade(); + } +} diff --git a/src/main/java/org/onap/dmaap/dbcapi/aaf/database/TableHandler.java b/src/main/java/org/onap/dmaap/dbcapi/aaf/database/TableHandler.java new file mode 100644 index 0000000..fe610ab --- /dev/null +++ b/src/main/java/org/onap/dmaap/dbcapi/aaf/database/TableHandler.java @@ -0,0 +1,115 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2017 AT&T 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.aaf.database; + +import java.util.*; +import java.lang.reflect.*; +import java.sql.*; + +class TableHandler<C> { + protected ConnectionFactory cf; + protected boolean haskey; + protected String delstmt; + protected String insorreplstmt; + protected String getstmt; + protected String liststmt; + protected String initstmt; + protected Class<C> cls; + protected DBFieldHandler[] fields; + private static Map<String, Map<String, DBFieldHandler.SqlOp>> exceptions = new HashMap<String, Map<String, DBFieldHandler.SqlOp>>(); + public static void setSpecialCase(String dbtabname, String dbfldname, DBFieldHandler.SqlOp handler) { + Map<String, DBFieldHandler.SqlOp> m = exceptions.get(dbtabname); + if (m == null) { + m = new HashMap<String, DBFieldHandler.SqlOp>(); + exceptions.put(dbtabname, m); + } + m.put(dbfldname, handler); + } + public static DBFieldHandler.SqlOp getSpecialCase(String dbtabname, String dbfldname) { + Map<String, DBFieldHandler.SqlOp> m = exceptions.get(dbtabname); + if (m != null) { + return(m.get(dbfldname)); + } + return(null); + } + protected TableHandler(Class<C> cls, String tabname, String keyname) throws Exception { + this(ConnectionFactory.getDefaultInstance(), cls, tabname, keyname); + } + protected TableHandler(ConnectionFactory cf, Class<C> cls, String tabname, String keyname) throws Exception { + this.cf = cf; + Connection c = null; + try { + c = cf.get(false); + setup(c.getMetaData(), cls, tabname, keyname); + } finally { + if (c != null) { + cf.release(c); + } + } + } + private void setup(DatabaseMetaData dmd, Class<C> cls, String tabname, String keyname) throws Exception { + this.cls = cls; + Vector<DBFieldHandler> h = new Vector<DBFieldHandler>(); + ResultSet rs = dmd.getColumns("", "public", tabname, null); + StringBuffer sb1 = new StringBuffer(); + StringBuffer sb2 = new StringBuffer(); + StringBuffer sb3 = new StringBuffer(); + int count = 0; + while (rs.next()) { + if (!rs.getString(3).equals(tabname)) { + continue; + } + String cname = rs.getString(4); + if (cname.equals(keyname)) { + haskey = true; + continue; + } + sb1.append(", ").append(cname); + sb2.append(", ?"); + sb3.append(", EXCLUDED.").append(cname); + count++; + h.add(new DBFieldHandler(cls, cname, count, getSpecialCase(tabname, cname))); + } + if (count == 0) { + throw new SQLException("Table " + tabname + " not found"); + } + String clist = sb1.substring(2); + String qlist = sb2.substring(2); + String elist = sb3.substring(2); + if (keyname != null && !haskey) { + throw new SQLException("Table " + tabname + " does not have key column " + keyname + " not found"); + } + if (haskey) { + count++; + h.add(new DBFieldHandler(cls, keyname, count, getSpecialCase(tabname, keyname))); + delstmt = "DELETE FROM " + tabname + " WHERE " + keyname + " = ?"; + insorreplstmt = "INSERT INTO " + tabname + " (" + clist + ", " + keyname + ") VALUES (" + qlist + ", ?) ON CONFLICT(" + keyname + ") DO UPDATE SET (" + clist + ") = (" + elist + ")"; + getstmt = "SELECT " + clist + ", " + keyname + " FROM " + tabname + " WHERE " + keyname + " = ?"; + liststmt = "SELECT " + clist + ", " + keyname + " FROM " + tabname; + } else { + delstmt = "DELETE FROM " + tabname; + initstmt = "INSERT INTO " + tabname + " (" + clist + ") VALUES (" + qlist + ")"; + insorreplstmt = "UPDATE " + tabname + " SET (" + clist + ") = (" + qlist + ")"; + getstmt = "SELECT " + clist + ", " + keyname + " FROM " + tabname; + } + fields = h.toArray(new DBFieldHandler[h.size()]); + } +} diff --git a/src/main/java/org/onap/dmaap/dbcapi/logging/BaseLoggingClass.java b/src/main/java/org/onap/dmaap/dbcapi/logging/BaseLoggingClass.java new file mode 100644 index 0000000..bb078cf --- /dev/null +++ b/src/main/java/org/onap/dmaap/dbcapi/logging/BaseLoggingClass.java @@ -0,0 +1,36 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2017 AT&T 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.logging; + +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; + +public abstract class BaseLoggingClass { + protected EELFLogger logger = EELFManager.getInstance().getLogger( super.getClass()); + protected static final EELFLogger appLogger = EELFManager.getInstance().getApplicationLogger(); + protected static final EELFLogger auditLogger = EELFManager.getInstance().getAuditLogger(); + protected static final EELFLogger debugLogger = EELFManager.getInstance().getDebugLogger(); + protected static final EELFLogger errorLogger = EELFManager.getInstance().getErrorLogger(); + protected static final EELFLogger metricsLogger = EELFManager.getInstance().getMetricsLogger(); + protected static final EELFLogger serverLogger = EELFManager.getInstance().getServerLogger(); + + +} diff --git a/src/main/java/org/onap/dmaap/dbcapi/logging/DmaapbcLogMessageEnum.java b/src/main/java/org/onap/dmaap/dbcapi/logging/DmaapbcLogMessageEnum.java new file mode 100644 index 0000000..86c5fe0 --- /dev/null +++ b/src/main/java/org/onap/dmaap/dbcapi/logging/DmaapbcLogMessageEnum.java @@ -0,0 +1,81 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2017 AT&T 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.logging; + +import com.att.eelf.i18n.EELFResourceManager; +import com.att.eelf.i18n.EELFResolvableErrorEnum; + +public enum DmaapbcLogMessageEnum implements EELFResolvableErrorEnum { +//0xx sample stock messages + MESSAGE_SAMPLE_NOARGS, + MESSAGE_SAMPLE_ONE_ARG, + MESSAGE_SAMPLE_TWO_ARGS, + +// 1xx Permission Errors + AAF_CREDENTIAL_ERROR, + CODEC_CREDENTIAL_ERROR, + PE_AUTHENTICATION_ERROR, + DR_PROV_AUTHORIZATION, + +// 2xx Availability Errors/Timeouts + DRIVER_UNAVAILABLE, + HTTP_CONNECTION_ERROR, + HTTP_CONNECTION_EXCEPTION, + UNKNOWN_HOST_EXCEPTION, + + +// 3xx Data Errors + IO_EXCEPTION, + SSL_HANDSHAKE_ERROR, + AAF_UNEXPECTED_RESPONSE, + PE_EXCEPTION, + SOCKET_EXCEPTION, + JSON_PARSING_ERROR, + DECRYPT_IO_ERROR, + +//4xx Schema Errors + DB_UPGRADE_ERROR, + DB_INIT_ERROR, + DB_UPDATE_ERROR, + DB_ACCESS_ERROR, + DB_FIELD_INIT_ERROR, + DB_ACCESS_INIT_ERROR, + DB_NO_FIELD_HANDLER, + + +// 5xx Business Process Errors + PREREQ_DMAAP_OBJECT, + PROV_OUT_OF_SYNC, + MM_CIRCULAR_REF, + TOPIC_CREATE_ERROR, + INGRESS_CREATE_ERROR, + FEED_PUB_PROV_ERROR, + FEED_SUB_PROV_ERROR, + MM_PUBLISH_ERROR, + EGRESS_CREATE_ERROR, + +// 900 Unknown Errors + UNEXPECTED_CONDITION; + + static { + EELFResourceManager.loadMessageBundle("logmsg"); + } +} diff --git a/src/main/java/org/onap/dmaap/dbcapi/logging/logmsg.properties b/src/main/java/org/onap/dmaap/dbcapi/logging/logmsg.properties new file mode 100644 index 0000000..cb8a939 --- /dev/null +++ b/src/main/java/org/onap/dmaap/dbcapi/logging/logmsg.properties @@ -0,0 +1,240 @@ +### +# ============LICENSE_START======================================================= +# org.onap.dmaap +# ================================================================================ +# Copyright (C) 2017 AT&T 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========================================================= +### + +# 0xx sample stock messages +MESSAGE_SAMPLE_NOARGS=\ + 01|\ + Ignore: demo msg with no arg|\ + No resolution|\ + An example of a message with no args + +MESSAGE_SAMPLE_ONE_ARG=\ + 02|\ + Ignore: demo msg with 1 arg {0}|\ + No resolution|\ + An example of a message with 1 arg + +MESSAGE_SAMPLE_TWO_ARGS=\ + 03|\ + Ignore: demo msg with arg1 {0} and arg2 {1}|\ + No resolution|\ + An example of a message with 2 args + + + +# 1xx Permission Errors +AAF_CREDENTIAL_ERROR=\ + 101|\ + Service credentials ({0}) are not valid for AAF connection|\ + Check credentials are valid in appropriate AAF environment.|\ + Connection to AAF was not allowed for the specified credentials. + +CODEC_CREDENTIAL_ERROR=\ + 102|\ + Failed to read CredentialCodecKeyfile {0} with error {1}|\ + Check if CredentialCodecKeyfile has been corrupted.|\ + CredentialCodecKeyfile is not in sync with application + +PE_AUTHENTICATION_ERROR=\ + 103|\ + User {0} perms {1} caught PolicyEngineException {1}|\ + User needs to be granted perm before access.|\ + Identified user was not authorized for the specific perm. + +DR_PROV_AUTHORIZATION=\ + 104|\ + Not authorized for API {0}|\ + Bus Controller host needs to be provisioned as a Node and an AUTHORIZED_HOST.|\ + DR Prov indicates that Bus Controller host is not authorized for the specified API. + +# 2xx Availability Errors/Timeouts +DRIVER_UNAVAILABLE=\ + 201|\ + Unable to load driver {0}. Error {1}|\ + Check that specified driver is installed and accessible to application.|\ + The software attempted to load a driver and was not successful. + +HTTP_CONNECTION_ERROR=\ + 202|\ + Exception during openConnection to {0} failed with {1}|\ + Confirm syntax of URL is correct and network access from this host is allowed.|\ + An attempt to URL.openConnection failed + +HTTP_CONNECTION_EXCEPTION=\ + 203|\ + Connection to {0} refused because {1}|\ + Check if this is the proper server.|\ + Application caught a ConnectionException + +UNKNOWN_HOST_EXCEPTION=\ + 204|\ + Caught exception {0} attempting to access {1}|\ + Confirm that host is in DNS|\ + Caught UnknownHostException when connecting to the designated host name. + +# 3xx Data Errors +IO_EXCEPTION=\ + 301|\ + IOexception {0}|\ + No resolution.|\ + Generic IO Exception condition + +SSL_HANDSHAKE_ERROR=\ + 302|\ + SSLHandshakeException from URL {0}|\ + Confirm that target host has proper SSL certificate for DNS value used to access it.|\ + SSLHandshake exception thrown on HttpsURLConnection method + +AAF_UNEXPECTED_RESPONSE=\ + 303|\ + rc= {0} :unable to {1} for {2}|\ + Check configuration for this AAF instance.|\ + Unexpected response from AAF for the intended action + +PE_EXCEPTION=\ + 304|\ + Trying to read {0} and caught PolicyEngineException {1}|\ + Check config file exists and has proper settings.|\ + An unexpected exception from PE was caught. + +SOCKET_EXCEPTION=\ + 305|\ + Caught exception {0} while {1}|\ + No comment.|\ + An unexpected socket exception was caught while performing the specified action. + +JSON_PARSING_ERROR=\ + 306|\ + ParsingException for object {0} using data:{1}|\ + No comment.|\ + The JSON data provided to the object was not in the expected format + + DECRYPT_IO_ERROR=\ + 307|\ + IO Error attempting using {0} to decrypt value {1}|\ + Check permissions of file set for property CredentialCodecKeyfile.|\ + Error using codec file for decryption. + +# 4xx Schema Errors + +DB_UPGRADE_ERROR=\ + 401|\ + Problem updating DB schema. {0}|\ + Examine stack trace for clues.|\ + The software was not able to process the sql file resources in the jar file. + +DB_INIT_ERROR=\ + 402|\ + Error initializing database access: {0}|\ + Correct configuration based on detail.|\ + The software was not able initialize objects from the DB. + +DB_UPDATE_ERROR=\ + 403|\ + Error while updating DB: {0}|\ + Correct configuration based on detail.|\ + The software was not able to update record(s) in the DB. + +DB_ACCESS_ERROR=\ + 404|\ + Database access problem: {0}|\ + Correct configuration based on detail.|\ + An exception related to DB access was caught and logged. + +DB_FIELD_INIT_ERROR=\ + 405|\ + Problem setting field {0} to {1} statement is {2}|\ + DB schema may be out of sync with code.|\ + SQLDate.set() failed to set field value. + +DB_ACCESS_INIT_ERROR=\ + 406|\ + Problem initializing sql access methods {0} |\ + No comment.|\ + Error encountered while initializing basic field types. + +DB_NO_FIELD_HANDLER=\ + 407|\ + No field handler for class {0} field {1} index {2} type {3}|\ + No comment.|\ + Missing field handler for specified code. + + +# 5xx Business Process Errors +PREREQ_DMAAP_OBJECT=\ + 501|\ + Attempt to access {} before dmaap object resource is available.|\ + No remediation.|\ + The dmaap object needs to be defined before attempting the desired access + +PROV_OUT_OF_SYNC=\ + 502|\ + Resource {0} with id {1} was not in sync with DR Prov.\ + May need manual sync steps.\ + The Bus Controller view of a resource does not match what was found on DR Prov + +MM_CIRCULAR_REF=\ + 503|\ + Trying to add edge from source {0} into Map belonging to {1}|\ + May indicate a provisioning error.|\ + Some error in logic is attempting to add an edge to a Map that is an edge. + +TOPIC_CREATE_ERROR=\ + 504|\ + Unable to create topic for {0} err={1} fields={2} msg={3}|\ + No comment.|\ + Reporting an error caught while creating a topic + +INGRESS_CREATE_ERROR=\ + 505|\ + rc={0} unable to create ingress rule for {1} on feed {2} to {3}|\ + No comment.|\ + Unexpected response while creating ingress rule + +FEED_PUB_PROV_ERROR=\ + 506|\ + For feed {0} resulting set of publishers do not match requested set of publishers {1} vs {2}|\ + No comment.|\ + The number of publishers on a feed do not match after provisioning request. + +FEED_SUB_PROV_ERROR=\ + 507|\ + For feed {0} i={1} url={2} err={3}|\ + No comment.|\ + An error occurred when provisioning subs on a feed. + +MM_PUBLISH_ERROR=\ + 508|\ + Unable to publish {0} provisioning message. rc={1} msg={2}|\ + No comment.|\ + An error occurred when publishing a message to MM + +EGRESS_CREATE_ERROR=\ + 509|\ + rc={0} unable to create egress rule for {1} on feed {2} to {3}|\ + No comment.|\ + Unexpected response while creating egress rule + +# 900 Unknown Errors +UNEXPECTED_CONDITION=\ + 901|\ + Unexpected exception encountered {0}|\ + No resolution|\ + An error to catch unexpected conditions. Hopefully a clue in the stack trace. diff --git a/src/main/java/org/onap/dmaap/dbcapi/model/ApiError.java b/src/main/java/org/onap/dmaap/dbcapi/model/ApiError.java new file mode 100644 index 0000000..8d8e23f --- /dev/null +++ b/src/main/java/org/onap/dmaap/dbcapi/model/ApiError.java @@ -0,0 +1,61 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2017 AT&T 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.model; + +import javax.xml.bind.annotation.XmlRootElement; + +@XmlRootElement +public class ApiError { + private int code; + private String message; + private String fields; + + public int getCode() { + return code; + } + public void setCode(int rc) { + this.code = rc; + } + public String getMessage() { + return message; + } + public void setMessage(String message) { + this.message = message; + } + public String getFields() { + return fields; + } + public void setFields(String fields) { + this.fields = fields; + } + public String toString() { + return String.format( "code=%d msg=%s fields=%s", this.code, this.message, this.fields ); + } + public boolean is2xx() { + + return code >= 200 && code < 300; + } + public void reset() { + code = 0; + message = null; + fields = null; + } +} diff --git a/src/main/java/org/onap/dmaap/dbcapi/model/BrTopic.java b/src/main/java/org/onap/dmaap/dbcapi/model/BrTopic.java new file mode 100644 index 0000000..a7041d0 --- /dev/null +++ b/src/main/java/org/onap/dmaap/dbcapi/model/BrTopic.java @@ -0,0 +1,65 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2017 AT&T 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.model; + +import javax.xml.bind.annotation.XmlRootElement; + +import org.apache.log4j.Logger; + +@XmlRootElement +public class BrTopic { + static final Logger logger = Logger.getLogger(BrTopic.class); + + private String brSource; + private String brTarget; + private int topicCount; + + // no-op constructor used by framework + public BrTopic() { + } + + public String getBrSource() { + return brSource; + } + + public void setBrSource(String brSource) { + this.brSource = brSource; + } + + public String getBrTarget() { + return brTarget; + } + + public void setBrTarget(String brTarget) { + this.brTarget = brTarget; + } + + public int getTopicCount() { + return topicCount; + } + + public void setTopicCount(int topicCount) { + this.topicCount = topicCount; + } + + + +} 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 new file mode 100644 index 0000000..a85f040 --- /dev/null +++ b/src/main/java/org/onap/dmaap/dbcapi/model/DR_Node.java @@ -0,0 +1,78 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2017 AT&T 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.model; + +import javax.xml.bind.annotation.XmlRootElement; + +@XmlRootElement +public class DR_Node extends DmaapObject { + private String fqdn; + private String dcaeLocationName; + private String hostName; + private String version; + + public DR_Node() { + + } + + public DR_Node( String f, + String dLN, + String hN, + String v ) { + this.fqdn = f; + this.dcaeLocationName = dLN; + this.hostName = hN; + this.version = v; + } + + public String getFqdn() { + return fqdn; + } + + public void setFqdn(String fqdn) { + this.fqdn = fqdn; + } + + public String getDcaeLocationName() { + return dcaeLocationName; + } + + public void setDcaeLocationName(String dcaeLocationName) { + this.dcaeLocationName = dcaeLocationName; + } + + public String getHostName() { + return hostName; + } + + public void setHostName(String hostName) { + this.hostName = hostName; + } + + public String getVersion() { + return version; + } + + public void setVersion(String version) { + this.version = 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 new file mode 100644 index 0000000..06598f7 --- /dev/null +++ b/src/main/java/org/onap/dmaap/dbcapi/model/DR_Pub.java @@ -0,0 +1,135 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2017 AT&T 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.model; + +import javax.xml.bind.annotation.XmlRootElement; + +import org.onap.dmaap.dbcapi.util.RandomString; + +@XmlRootElement +public class DR_Pub extends DmaapObject { + + private String dcaeLocationName; + private String username; + private String userpwd; + private String feedId; + private String pubId; + + + public DR_Pub() { + status = DmaapObject_Status.EMPTY; + + } + + public DR_Pub( String dLN ) { + this.dcaeLocationName = dLN; + this.status = DmaapObject_Status.STAGED; + } + + public DR_Pub( String dLN, + String uN, + String uP, + String fI, + String pI ) { + this.dcaeLocationName = dLN; + this.username = uN; + this.userpwd = uP; + this.feedId = fI; + this.pubId = pI; + this.status = DmaapObject_Status.VALID; + } + + + public DR_Pub( String dLN, + String uN, + String uP, + String fI ) { + this.dcaeLocationName = dLN; + this.username = uN; + this.userpwd = uP; + this.feedId = fI; + this.pubId = fI + "." + DR_Pub.nextKey(); + this.status = DmaapObject_Status.VALID; + } + + + public String getDcaeLocationName() { + return dcaeLocationName; + } + + public void setDcaeLocationName(String dcaeLocationName) { + this.dcaeLocationName = dcaeLocationName; + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getUserpwd() { + return userpwd; + } + + public void setUserpwd(String userpwd) { + this.userpwd = userpwd; + } + + public String getFeedId() { + return feedId; + } + + public void setFeedId(String feedId) { + this.feedId = feedId; + } + + public String getPubId() { + return pubId; + } + + public void setPubId(String pubId) { + this.pubId = pubId; + } + + public void setNextPubId() { + this.pubId = this.feedId + "." + DR_Pub.nextKey(); + } + + public DR_Pub setRandomUserName() { + RandomString r = new RandomString(15); + this.username = "tmp_" + r.nextString(); + return this; + } + public DR_Pub setRandomPassword() { + RandomString r = new RandomString(15); + this.userpwd = r.nextString(); + return this; + } + + public static String nextKey() { + RandomString ri = new RandomString(5); + return ri.nextString(); + + } + +} 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 new file mode 100644 index 0000000..6d36a89 --- /dev/null +++ b/src/main/java/org/onap/dmaap/dbcapi/model/DR_Sub.java @@ -0,0 +1,232 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2017 AT&T 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.model; + +import java.nio.charset.StandardCharsets; + +import javax.xml.bind.annotation.XmlRootElement; + +import org.json.simple.JSONObject; +import org.json.simple.parser.JSONParser; +import org.json.simple.parser.ParseException; +import org.onap.dmaap.dbcapi.logging.DmaapbcLogMessageEnum; + +@XmlRootElement +public class DR_Sub extends DmaapObject { + + private String dcaeLocationName; + private String username; + private String userpwd; + private String feedId; + private String deliveryURL; + private String logURL; + private String subId; + private boolean use100; + private boolean suspended; + private String owner; + + public String getOwner() { + return owner; + } + + public void setOwner(String owner) { + this.owner = owner; + } + + public boolean isSuspended() { + return suspended; + } + + public void setSuspended(boolean suspended) { + this.suspended = suspended; + } + + + + public boolean isUse100() { + return use100; + } + + public void setUse100(boolean use100) { + this.use100 = use100; + } + + public DR_Sub() { + + } + + public DR_Sub( String dLN, + String uN, + String uP, + String fI, + String dU, + String lU, + boolean u100 ) { + this.dcaeLocationName = dLN; + this.username = uN; + this.userpwd = uP; + this.feedId = fI; + this.deliveryURL = dU; + this.logURL = lU; + this.use100 = u100; + 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 ) { + errorLogger.error( DmaapbcLogMessageEnum.JSON_PARSING_ERROR, "DR_Sub", json ); + this.setStatus( DmaapObject_Status.INVALID ); + return; + } + + this.setOwner( (String) jsonObj.get("subscriber")); + this.setSuspended( (boolean) jsonObj.get("suspend")); + + JSONObject links = (JSONObject) jsonObj.get("links"); + String url = (String) links.get("feed"); + this.setFeedId( url.substring( url.lastIndexOf('/')+1, url.length() )); + url = (String) links.get("self"); + this.setSubId( url.substring( url.lastIndexOf('/')+1, url.length() )); + logger.info( "feedid="+ this.getFeedId() ); + this.setLogURL( (String) links.get("log") ); + + JSONObject del = (JSONObject) jsonObj.get("delivery"); + 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 getDcaeLocationName() { + return dcaeLocationName; + } + + public void setDcaeLocationName(String dcaeLocationName) { + this.dcaeLocationName = dcaeLocationName; + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getUserpwd() { + return userpwd; + } + + public void setUserpwd(String userpwd) { + this.userpwd = userpwd; + } + + public String getFeedId() { + return feedId; + } + + public void setFeedId(String feedId) { + this.feedId = feedId; + } + + public String getDeliveryURL() { + return deliveryURL; + } + + public void setDeliveryURL(String deliveryURL) { + this.deliveryURL = deliveryURL; + } + + public String getLogURL() { + return logURL; + } + + public void setLogURL(String logURL) { + this.logURL = logURL; + } + + public String getSubId() { + return subId; + } + + public void setSubId(String subId) { + this.subId = subId; + } + + + + public byte[] getBytes() { + return toProvJSON().getBytes(StandardCharsets.UTF_8); + } + // returns the DR_Sub object in JSON that conforms to DR Prov Server expectations + public String toProvJSON() { + + // 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... + // Similarly, in the 1704 Release, a new subscriber attribute "follow_redirect" was introduced. + // We are setting it to "true" because that is the general behavior desired in OpenDCAE. + // But it is really a no-op for OpenDCAE because we've deployed DR with the SYSTEM-level parameter for FOLLOW_REDIRECTS set to true. + // In the event we abandon that, then setting the sub attribute to true will be a good thing. + // TODO: + // - introduce Bus Controller API support for these attributes + // - store the default values in the DB + String postJSON = String.format("{\"delivery\": {\"url\": \"%s\", \"user\": \"%s\", \"password\": \"%s\", \"use100\": \"%s\"}, \"metadataOnly\": %s, \"groupid\": \"%s\", \"follow_redirect\": %s }", + this.getDeliveryURL(), + this.getUsername(), + this.getUserpwd(), + this.isUse100(), + "false", + "0", + "true"); + + 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}", + dcaeLocationName, + username, + userpwd, + feedId, + deliveryURL, + logURL, + subId, + use100, + suspended, + owner + ); + return rc; + } +} diff --git a/src/main/java/org/onap/dmaap/dbcapi/model/DcaeLocation.java b/src/main/java/org/onap/dmaap/dbcapi/model/DcaeLocation.java new file mode 100644 index 0000000..8248ef1 --- /dev/null +++ b/src/main/java/org/onap/dmaap/dbcapi/model/DcaeLocation.java @@ -0,0 +1,103 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2017 AT&T 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.model; + +import javax.xml.bind.annotation.XmlRootElement; + +import org.apache.log4j.Logger; + +@XmlRootElement +public class DcaeLocation extends DmaapObject { + static final Logger logger = Logger.getLogger(MR_Cluster.class); + private String clli; + private String dcaeLayer; + private String dcaeLocationName; + private String openStackAvailabilityZone; + private String subnet; + + + + public DcaeLocation() { + + } + + public DcaeLocation( String c, + String dL, + String dLN, + String oSAZ, + String s ) { + + this.clli = c; + this.dcaeLayer = dL; + this.dcaeLocationName = dLN; + this.openStackAvailabilityZone = oSAZ; + this.subnet = s; + } + + public String getClli() { + return clli; + } + + public void setClli(String clli) { + this.clli = clli; + } + + public String getDcaeLayer() { + return dcaeLayer; + } + + public void setDcaeLayer(String dcaeLayer) { + this.dcaeLayer = dcaeLayer; + } + public boolean isCentral() { + return dcaeLayer != null && dcaeLayer.contains("central"); + } + public boolean isLocal() { + return dcaeLayer != null && dcaeLayer.contains("local"); + } + + public String getDcaeLocationName() { + return dcaeLocationName; + } + + public void setDcaeLocationName(String dcaeLocationName) { + this.dcaeLocationName = dcaeLocationName; + } + + + + public String getOpenStackAvailabilityZone() { + return openStackAvailabilityZone; + } + + public void setOpenStackAvailabilityZone(String openStackAvailabilityZone) { + this.openStackAvailabilityZone = openStackAvailabilityZone; + } + + public String getSubnet() { + return subnet; + } + + public void setSubnet(String subnet) { + this.subnet = subnet; + } + +} diff --git a/src/main/java/org/onap/dmaap/dbcapi/model/Dmaap.java b/src/main/java/org/onap/dmaap/dbcapi/model/Dmaap.java new file mode 100644 index 0000000..3f2ef82 --- /dev/null +++ b/src/main/java/org/onap/dmaap/dbcapi/model/Dmaap.java @@ -0,0 +1,132 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2017 AT&T 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.model; + +import javax.xml.bind.annotation.XmlRootElement; + +import org.apache.log4j.Logger; + +@XmlRootElement +public class Dmaap extends DmaapObject { + + private String version; + private String topicNsRoot; + private String dmaapName; + private String drProvUrl; + private String bridgeAdminTopic; + private String loggingUrl; + private String nodeKey; + private String accessKeyOwner; + + + + // no-op constructor used by framework + public Dmaap() { + + } + + public Dmaap( String ver, + String tnr, + String dn, + String dpu, + String lu, + String bat, + String nk, + String ako ) { + this.version = ver; + this.topicNsRoot = tnr; + this.dmaapName = dn; + this.drProvUrl = dpu; + this.bridgeAdminTopic = bat; + this.loggingUrl = lu; + this.nodeKey = nk; + this.accessKeyOwner = ako; + this.setStatus( DmaapObject_Status.NEW ); + } + + public String getVersion() { + return version; + } + + public void setVersion(String version) { + this.version = version; + } + + public String getTopicNsRoot() { + return topicNsRoot; + } + + public void setTopicNsRoot(String topicNsRoot) { + this.topicNsRoot = topicNsRoot; + } + + public String getDmaapName() { + return dmaapName; + } + + public void setDmaapName(String dmaapName) { + this.dmaapName = dmaapName; + } + + public String getDrProvUrl() { + return drProvUrl; + } + + public void setDrProvUrl(String drProvUrl) { + this.drProvUrl = drProvUrl; + } + + + public String getNodeKey() { + return nodeKey; + } + + public void setNodeKey(String nodeKey) { + this.nodeKey = nodeKey; + } + + public String getAccessKeyOwner() { + return accessKeyOwner; + } + + public void setAccessKeyOwner(String accessKeyOwner) { + this.accessKeyOwner = accessKeyOwner; + } + + + public String getBridgeAdminTopic() { + return bridgeAdminTopic; + } + + public void setBridgeAdminTopic(String bridgeAdminTopic) { + this.bridgeAdminTopic = bridgeAdminTopic; + } + + public String getLoggingUrl() { + return loggingUrl; + } + + public void setLoggingUrl(String loggingUrl) { + this.loggingUrl = loggingUrl; + } + + +} diff --git a/src/main/java/org/onap/dmaap/dbcapi/model/DmaapObject.java b/src/main/java/org/onap/dmaap/dbcapi/model/DmaapObject.java new file mode 100644 index 0000000..567e042 --- /dev/null +++ b/src/main/java/org/onap/dmaap/dbcapi/model/DmaapObject.java @@ -0,0 +1,127 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2017 AT&T 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.model; + +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Date; +import java.util.TimeZone; + +import javax.xml.bind.annotation.XmlRootElement; + +import org.onap.dmaap.dbcapi.logging.BaseLoggingClass; + +@XmlRootElement +public abstract class DmaapObject extends BaseLoggingClass { + protected Date lastMod; + protected DmaapObject_Status status; + + public Date getLastMod() { + return lastMod; + } + + public void setLastMod(Date lastMod) { + this.lastMod = lastMod; + } + + public void setLastMod() { + this.lastMod = Calendar.getInstance(TimeZone.getTimeZone("UTC")).getTime(); + } + + public enum DmaapObject_Status { + EMPTY, + NEW, + STAGED, + VALID, + INVALID, + DELETED + } + public DmaapObject_Status getStatus() { + return status; + } + + public void setStatus(DmaapObject_Status status) { + this.status = status; + } + + public boolean isStatusValid() { + if ( this.status == DmaapObject_Status.VALID ) { + return true; + } + return false; + } + + /* + * TODO: get this working so arrays and sub-class within an Object can be logged + * + public String toString() { + return classToString( this ); + } + + private String classToString( Object obj ) { + Field[] fields = obj.getClass().getDeclaredFields(); + StringBuilder res = new StringBuilder( "{"); + boolean first = true; + for ( Field field: fields ) { + logger.info( field.getName() + " toString=" + field.toString() + " toGenericString=" + field.toGenericString()); + if ( first ) { + first = false; + } else { + res.append( ", "); + } + + + field.setAccessible(true); // avoid IllegalAccessException + + + Class<?> t = field.getType(); + + if ( t == String.class ) { + res.append( "\"" ).append( field.getName() ).append( "\": \""); + + try { + res.append(field.get(this)); + } catch ( IllegalAccessException iae) { + res.append( "UNK(iae)"); + } catch (IllegalArgumentException iae2 ) { + res.append( "UNK(iae2)"); + } catch ( NullPointerException npe ) { + res.append( "UNK(npe)"); + } catch ( ExceptionInInitializerError eie ) { + res.append( "UNK(eie)"); + } + res.append( "\""); + } else if ( t == ArrayList.class ){ + res.append( "["); + res.append( classToString( field )); + res.append( "]"); + + } + } + res.append( "}"); + return( res.toString()); + + + } + */ + +} diff --git a/src/main/java/org/onap/dmaap/dbcapi/model/Feed.java b/src/main/java/org/onap/dmaap/dbcapi/model/Feed.java new file mode 100644 index 0000000..9f7b3fc --- /dev/null +++ b/src/main/java/org/onap/dmaap/dbcapi/model/Feed.java @@ -0,0 +1,299 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2017 AT&T 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.model; + +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; + +import javax.xml.bind.annotation.XmlRootElement; + +import org.json.simple.*; +import org.json.simple.parser.*; +import org.onap.dmaap.dbcapi.service.DmaapService; + +@XmlRootElement +public class Feed extends DmaapObject { + + private String feedId; + + private String feedName; + private String feedVersion; + private String feedDescription; + private String owner; + private String asprClassification; + private String publishURL; + private String subscribeURL; + private boolean suspended; + private String logURL; + private String formatUuid; + + private ArrayList<DR_Pub> pubs; + private ArrayList<DR_Sub> subs; + + + + public boolean isSuspended() { + return suspended; + } + + public void setSuspended(boolean suspended) { + this.suspended = suspended; + } + + public String getSubscribeURL() { + return subscribeURL; + } + + public void setSubscribeURL(String subscribeURL) { + this.subscribeURL = subscribeURL; + } + + + + public Feed() { + this.pubs = new ArrayList<DR_Pub>(); + this.subs = new ArrayList<DR_Sub>(); + this.setStatus( DmaapObject_Status.EMPTY ); + + } + + public Feed( String name, + String version, + String description, + String owner, + String aspr + ) { + this.feedName = name; + this.feedVersion = version; + this.feedDescription = description; + this.owner = owner; + this.asprClassification = aspr; + this.pubs = new ArrayList<DR_Pub>(); + this.subs = new ArrayList<DR_Sub>(); + this.setStatus( DmaapObject_Status.NEW ); + + } + + // expects a String in JSON format, with known fields to populate Feed object + public Feed ( String json ) { + JSONParser parser = new JSONParser(); + JSONObject jsonObj; + + try { + jsonObj = (JSONObject) parser.parse( json ); + } catch ( ParseException pe ) { + logger.error( "Error parsing provisioning data: " + json ); + this.setStatus( DmaapObject_Status.INVALID ); + return; + } + this.setFeedName( (String) jsonObj.get("name")); + + + this.setFeedVersion( (String) jsonObj.get("version")); + this.setFeedDescription( (String) jsonObj.get("description")); + this.setOwner( (String) jsonObj.get("publisher")); + + this.setSuspended( (boolean) jsonObj.get("suspend")); + JSONObject links = (JSONObject) jsonObj.get("links"); + String url = (String) links.get("publish"); + this.setPublishURL( url ); + this.setFeedId( url.substring( url.lastIndexOf('/')+1, url.length() )); + logger.info( "feedid="+ this.getFeedId() ); + this.setSubscribeURL( (String) links.get("subscribe") ); + this.setLogURL( (String) links.get("log") ); + JSONObject auth = (JSONObject) jsonObj.get("authorization"); + this.setAsprClassification( (String) auth.get("classification")); + JSONArray pubs = (JSONArray) auth.get( "endpoint_ids"); + int i; + ArrayList<DR_Pub> dr_pub = new ArrayList<DR_Pub>(); + this.subs = new ArrayList<DR_Sub>(); + + for( i = 0; i < pubs.size(); i++ ) { + JSONObject entry = (JSONObject) pubs.get(i); + dr_pub.add( new DR_Pub( "someLocation", + (String) entry.get("id"), + (String) entry.get("password"), + this.getFeedId(), + this.getFeedId() + "." + DR_Pub.nextKey() )); + + } + this.setPubs( dr_pub ); + + this.setStatus( DmaapObject_Status.VALID ); + + } + + public String getFeedId() { + return feedId; + } + + public void setFeedId(String feedId) { + this.feedId = feedId; + } + + public String getFeedName() { + return feedName; + } + + public void setFeedName(String feedName) { + this.feedName = feedName; + } + + public String getFeedVersion() { + return feedVersion; + } + + public void setFeedVersion(String feedVersion) { + this.feedVersion = feedVersion; + } + + public String getFeedDescription() { + return feedDescription; + } + + public void setFeedDescription(String feedDescription) { + this.feedDescription = feedDescription; + } + + public String getOwner() { + return owner; + } + + public void setOwner(String owner) { + this.owner = owner; + } + + public String getAsprClassification() { + return asprClassification; + } + + public void setAsprClassification(String asprClassification) { + this.asprClassification = asprClassification; + } + + public String getPublishURL() { + return publishURL; + } + + public void setPublishURL(String publishURL) { + this.publishURL = publishURL; + } + + public String getLogURL() { + return logURL; + } + + public void setLogURL(String logURL) { + this.logURL = logURL; + } + + + + public String getFormatUuid() { + return formatUuid; + } + + public void setFormatUuid(String formatUuid) { + this.formatUuid = formatUuid; + } + + // returns the Feed object in JSON that conforms to DR Prov Server expectations + public String toProvJSON() { + + ArrayList<DR_Pub> pubs = this.getPubs(); + String postJSON = String.format("{\"name\": \"%s\", \"version\": \"%s\", \"description\": \"%s\", \"suspend\": %s, \"authorization\": { \"classification\": \"%s\", ", + this.getFeedName(), + this.getFeedVersion(), + this.getFeedDescription(), + this.isSuspended() , + this.getAsprClassification() + ); + int i; + postJSON += "\"endpoint_addrs\": [],\"endpoint_ids\": ["; + String comma = ""; + for( i = 0 ; i < pubs.size(); i++) { + postJSON += String.format(" %s{\"id\": \"%s\",\"password\": \"%s\"}", + comma, + pubs.get(i).getUsername(), + pubs.get(i).getUserpwd() + ) ; + comma = ","; + } + postJSON += "]}}"; + + logger.info( "postJSON=" + postJSON); + return postJSON; + } + + public ArrayList<DR_Pub> getPubs() { + return pubs; + } + + public void setPubs( ArrayList<DR_Pub> pubs) { + this.pubs = pubs; + } + + public ArrayList<DR_Sub> getSubs() { + return subs; + } + + public void setSubs( ArrayList<DR_Sub> subs) { + this.subs = subs; + } + + public byte[] getBytes() { + return toProvJSON().getBytes(StandardCharsets.UTF_8); + } + + public static String getSubProvURL( String feedId ) { + String ret = new String(); + ret = new DmaapService().getDmaap().getDrProvUrl() + "/subscribe/" + feedId ; + return ret; + } + + @Override + public String toString() { + String rc = String.format ( "Feed: {feedId=%s feedName=%s feedVersion=%s feedDescription=%s owner=%s asprClassification=%s publishURL=%s subscriberURL=%s suspended=%s logURL=%s formatUuid=%s}", + feedId, + feedName, + feedVersion, + feedDescription, + owner, + asprClassification, + publishURL, + subscribeURL, + suspended, + logURL, + formatUuid + + + ); + + for( DR_Pub pub: pubs) { + rc += "\n" + pub.toString(); + } + + for( DR_Sub sub: subs ) { + rc += "\n" + sub.toString(); + } + return rc; + } +} diff --git a/src/main/java/org/onap/dmaap/dbcapi/model/MR_Client.java b/src/main/java/org/onap/dmaap/dbcapi/model/MR_Client.java new file mode 100644 index 0000000..dc43cc0 --- /dev/null +++ b/src/main/java/org/onap/dmaap/dbcapi/model/MR_Client.java @@ -0,0 +1,122 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2017 AT&T 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.model; + +import java.util.Date; + +import javax.xml.bind.annotation.XmlRootElement; + + + + +import org.onap.dmaap.dbcapi.aaf.database.DatabaseClass; + +@XmlRootElement +public class MR_Client extends DmaapObject { + + private String dcaeLocationName; + private String topicURL; + private String fqtn; + private String clientRole; + private String[] action; + private String mrClientId; + + + public MR_Client() { + this.mrClientId = DatabaseClass.getNextClientId(); + this.lastMod = new Date(); + this.setLastMod(); + debugLogger.debug( "MR_Client constructor " + this.lastMod ); + + } + + public MR_Client( String dLN, + String f, + String cR, + String[] a ) { + this.dcaeLocationName = dLN; + this.fqtn = f; + this.clientRole = cR; + int i = 0; + + if ( this.action == null ) { + this.action = new String[a.length]; + } + for( String aa : a ) { + this.action[i++] = new String( aa ); + } + this.setStatus( DmaapObject_Status.NEW ); + this.mrClientId = DatabaseClass.getNextClientId(); + this.setLastMod(); + debugLogger.debug( "MR_Client constructor w initialization " + this.lastMod ); + } + + public String getDcaeLocationName() { + return dcaeLocationName; + } + + public void setDcaeLocationName(String dcaeLocationName) { + this.dcaeLocationName = dcaeLocationName; + } + + public String getFqtn() { + return fqtn; + } + + public void setFqtn(String fqtn) { + this.fqtn = fqtn; + } + + public String getClientRole() { + return clientRole; + } + + public void setClientRole(String clientRole) { + this.clientRole = clientRole; + } + + public String[] getAction() { + return action; + } + + public void setAction(String[] action) { + this.action = action; + } + + public String getMrClientId() { + return mrClientId; + } + + public void setMrClientId(String mrClientId) { + this.mrClientId = mrClientId; + } + + + + public String getTopicURL() { + return topicURL; + } + + public void setTopicURL(String topicURL) { + this.topicURL = topicURL; + } + +} diff --git a/src/main/java/org/onap/dmaap/dbcapi/model/MR_Cluster.java b/src/main/java/org/onap/dmaap/dbcapi/model/MR_Cluster.java new file mode 100644 index 0000000..d8ebc8b --- /dev/null +++ b/src/main/java/org/onap/dmaap/dbcapi/model/MR_Cluster.java @@ -0,0 +1,129 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2017 AT&T 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.model; + +import java.util.Date; + +import javax.xml.bind.annotation.XmlRootElement; + + + +@XmlRootElement +public class MR_Cluster extends DmaapObject { + + private String dcaeLocationName; + private String fqdn; + private String[] hosts; + //private DmaapTimestamp lastMod; + private String topicProtocol; + private String topicPort; + + + // TODO: make this a system property + private static String defaultTopicProtocol = "https"; + private static String defaultTopicPort = "3905"; + + + + + public MR_Cluster() { + this.topicProtocol = defaultTopicProtocol; + this.topicPort = defaultTopicPort; + this.lastMod = new Date(); + + debugLogger.debug( "MR_Cluster constructor " + this.lastMod ); + + } + + public MR_Cluster( String dLN, + String f, + String a, + String[] h ) { + this.dcaeLocationName = dLN; + this.fqdn = f; + this.hosts[0] = h[0]; + this.hosts[1] = h[1]; + this.hosts[2] = h[2]; + this.topicProtocol = defaultTopicProtocol; + this.topicPort = defaultTopicPort; + + debugLogger.debug( "MR_Cluster constructor w initialization complete" + this.lastMod ); + } + + public String getDcaeLocationName() { + return dcaeLocationName; + } + + public void setDcaeLocationName(String dcaeLocationName) { + this.dcaeLocationName = dcaeLocationName; + } + + public String getFqdn() { + return fqdn; + } + + public void setFqdn(String fqdn) { + this.fqdn = fqdn; + } + + public String[] getHosts() { + return hosts; + } + + public void setHosts(String[] hosts) { + this.hosts = hosts; + } + + public String getTopicProtocol() { + return topicProtocol; + } + + public void setTopicProtocol(String topicProtocol) { + this.topicProtocol = topicProtocol; + } + + public String getTopicPort() { + return topicPort; + } + + public void setTopicPort(String topicPort) { + this.topicPort = topicPort; + } + + + + public String genTopicURL(String overideFqdn, String topic) { + + StringBuilder str = new StringBuilder( topicProtocol ); + str.append("://") + .append( overideFqdn != null ? overideFqdn : fqdn) + .append(":") + .append(topicPort) + .append("/events/") + .append(topic); + + return str.toString(); + + + } + + +} diff --git a/src/main/java/org/onap/dmaap/dbcapi/model/MirrorMaker.java b/src/main/java/org/onap/dmaap/dbcapi/model/MirrorMaker.java new file mode 100644 index 0000000..b1a2d3c --- /dev/null +++ b/src/main/java/org/onap/dmaap/dbcapi/model/MirrorMaker.java @@ -0,0 +1,203 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2017 AT&T 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.model; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.Set; + +import org.apache.log4j.Logger; +import org.onap.dmaap.dbcapi.logging.DmaapbcLogMessageEnum; +import org.onap.dmaap.dbcapi.service.MirrorMakerService; + +public class MirrorMaker extends DmaapObject { + static final Logger logger = Logger.getLogger(MirrorMaker.class); + + private String sourceCluster; + private String targetCluster; + private String mmName; + private ArrayList<String> topics; //re-using this var name for backwards DB compatibility + + private Set<ReplicationVector> vectors; + + + public MirrorMaker(){ + + } + + public MirrorMaker(String source, String target) { + sourceCluster = source; + targetCluster = target; + mmName = genKey(source, target); + vectors = new HashSet<ReplicationVector>(); + topics = new ArrayList<String>(); + + } + + public String getMmName() { + return mmName; + } + + public void setMmName(String mmName) { + this.mmName = mmName; + } + + + public void addVector( String fqtn, String source, String target ) { + logger.info( "addVector: fqtn=" + fqtn + " source=" + source + " target=" + target ); + if ( ! sourceCluster.equals( source ) ){ + errorLogger.error( DmaapbcLogMessageEnum.MM_CIRCULAR_REF, source, sourceCluster ); + } + vectors.add(new ReplicationVector( fqtn, source, target )); + } + + public void delVector( String fqtn, String source, String target ) { + vectors.remove(new ReplicationVector( fqtn, source, target)); + } + + + + public String toJSON() { + StringBuilder str = new StringBuilder( "{ \"source\": " + sourceCluster + ",\"topics\": [" ); + int numTargets = 0; + for (ReplicationVector rv: vectors) { + if ( numTargets > 0 ) { + str.append( ","); + } + str.append( " \"target\": " + rv.getTargetCluster() + ", \"topic\": " + rv.getFqtn()); + numTargets++; + } + str.append( "] }" ); + + return str.toString(); + } + + + // returns the JSON for MM message containing which Topics to replicate + /* + * example: + * + { + "messageID":"12349", + "updateWhiteList": + { + "name":"Global1ToGlobal3", + "whitelist":"org.openecomp.dcae.topic1,org.openecomp.dcae.topic2" + } + } + */ + public String updateWhiteList() { + StringBuilder str = new StringBuilder( "{ \"messageID\": \"" + MirrorMakerService.genTransactionId() + "\", \"updateWhiteList\": {" ); + str.append( " \"name\": \"" + this.getMmName() + "\", \"whitelist\": \"" ); + int numTargets = 0; + + //for (ReplicationVector rv: vectors) { + for (String rv: topics) { + if ( numTargets > 0 ) { + str.append( ","); + } + //str.append( rv.getFqtn() ); + str.append( rv ); + numTargets++; + } + str.append( "\" } }" ); + + return str.toString(); + } + + // returns the JSON for MM message indicating that a MM agent is needed between two clusters + // example: + /* + * + { + "messageID":"12345" + "createMirrorMaker": + { + "name":"Global1ToGlobal2", + "consumer":"192.168.0.1:2181", + "producer":"192.168.0.2:9092" + } + } + */ + public String createMirrorMaker() { + StringBuilder str = new StringBuilder( "{ \"messageID\": \"" + MirrorMakerService.genTransactionId() + "\", \"createMirrorMaker\": {" ); + str.append( " \"name\": \"" + this.getMmName() + "\", " ); + str.append( " \"consumer\": \"" + this.sourceCluster + ":2181\", " ); + str.append( " \"producer\": \"" + this.targetCluster + ":9092\" "); + + str.append( " } }" ); + + return str.toString(); + } + + + public String getSourceCluster() { + return sourceCluster; + } + + public void setSourceCluster(String sourceCluster) { + this.sourceCluster = sourceCluster; + } + + public String getTargetCluster() { + return targetCluster; + } + + public void setTargetCluster(String targetCluster) { + this.targetCluster = targetCluster; + } + + + public Set<ReplicationVector> getVectors() { + return vectors; + } + + public void setVectors(Set<ReplicationVector> vectors) { + this.vectors = vectors; + } + public ArrayList<String> getTopics() { + return topics; + } + + //public void setVectors(Set<ReplicationVector> vectors) { + public void setTopics(ArrayList<String> topics) { + this.topics = topics; + } + + + public static String genKey( String s, String t) { + StringBuilder str = new StringBuilder(); + str.append(s); + str.append("-To-"); + str.append(t); + return str.toString(); + } + + + + public void addTopic( String topic ) { + topics.add(topic); + } + + public int getTopicCount() { + return topics.size(); + } +} diff --git a/src/main/java/org/onap/dmaap/dbcapi/model/ReplicationType.java b/src/main/java/org/onap/dmaap/dbcapi/model/ReplicationType.java new file mode 100644 index 0000000..49b93a6 --- /dev/null +++ b/src/main/java/org/onap/dmaap/dbcapi/model/ReplicationType.java @@ -0,0 +1,83 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2017 AT&T 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.model; + +import java.util.HashMap; +import java.util.Map; + +import javax.xml.bind.annotation.XmlRootElement; + + +@XmlRootElement +public enum ReplicationType { + REPLICATION_NOT_SPECIFIED(0), + REPLICATION_NONE(1), + REPLICATION_EDGE_TO_CENTRAL(10), + REPLICATION_EDGE_TO_CENTRAL_TO_GLOBAL(110), + REPLICATION_CENTRAL_TO_EDGE(20), + REPLICATION_CENTRAL_TO_GLOBAL(21), + REPLICATION_GLOBAL_TO_CENTRAL(30), + REPLICATION_GLOBAL_TO_CENTRAL_TO_EDGE(120); + + private int value; + private static Map map = new HashMap<>(); + + private ReplicationType(int value) { + this.value = value; + } + + static { + for (ReplicationType repType : ReplicationType.values()) { + map.put(repType.value, repType); + } + } + + public static ReplicationType valueOf(int repType) { + return (ReplicationType) map.get(repType); + } + + public int getValue() { + return value; + } + + static public ReplicationType Validator( String input ){ + + ReplicationType t; + try { + t = ReplicationType.valueOf( input ); + } catch ( IllegalArgumentException e ) { + t = REPLICATION_NOT_SPECIFIED; + } + return t; + } + + public boolean involvesGlobal() { + if ( this.compareTo(REPLICATION_CENTRAL_TO_GLOBAL) == 0 || + this.compareTo(REPLICATION_GLOBAL_TO_CENTRAL) == 0 || + this.compareTo(REPLICATION_EDGE_TO_CENTRAL_TO_GLOBAL) == 0 || + this.compareTo(REPLICATION_GLOBAL_TO_CENTRAL_TO_EDGE) == 0) { + return true; + } + return false; + } + + + +}
\ No newline at end of file diff --git a/src/main/java/org/onap/dmaap/dbcapi/model/ReplicationVector.java b/src/main/java/org/onap/dmaap/dbcapi/model/ReplicationVector.java new file mode 100644 index 0000000..add3998 --- /dev/null +++ b/src/main/java/org/onap/dmaap/dbcapi/model/ReplicationVector.java @@ -0,0 +1,100 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2017 AT&T 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.model; + +public class ReplicationVector { + + public enum ReplicationVector_Status { + EMPTY, + NEW, + STAGED, + VALID, + INVALID, + INVALID_DUP, + DELETED + } + + String fqtn; + String sourceCluster; + String targetCluster; + ReplicationVector_Status status; + + public ReplicationVector(){ + + } + + public ReplicationVector(String fqtn, String sourceCluster, + String targetCluster) { + super(); + this.fqtn = fqtn; + this.sourceCluster = sourceCluster; + this.targetCluster = targetCluster; + } + + public String getFqtn() { + return fqtn; + } + + public void setFqtn(String fqtn) { + this.fqtn = fqtn; + } + + public String getSourceCluster() { + return sourceCluster; + } + + public void setSourceCluster(String sourceCluster) { + this.sourceCluster = sourceCluster; + } + + public String getTargetCluster() { + return targetCluster; + } + + public void setTargetCluster(String targetCluster) { + this.targetCluster = targetCluster; + } + + public int hashCode() { + StringBuilder tmp = new StringBuilder( this.fqtn ); + tmp.append(this.sourceCluster); + tmp.append(this.targetCluster); + + return tmp.toString().hashCode(); + } + private static boolean xeq(String s1, String s2) { + if (s1 == null) { + return(s2 == null); + } else { + return(s1.equals(s2)); + } + } + public boolean equals(Object o) { + if (o == this) { + return(true); + } + if (!(o instanceof ReplicationVector)) { + return(false); + } + ReplicationVector x = (ReplicationVector)o; + return(xeq(fqtn, x.fqtn) && xeq(sourceCluster, x.sourceCluster) && xeq(targetCluster, x.targetCluster)); + } +} diff --git a/src/main/java/org/onap/dmaap/dbcapi/model/Topic.java b/src/main/java/org/onap/dmaap/dbcapi/model/Topic.java new file mode 100644 index 0000000..712c2eb --- /dev/null +++ b/src/main/java/org/onap/dmaap/dbcapi/model/Topic.java @@ -0,0 +1,193 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2017 AT&T 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.model; + +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.Date; + +import javax.xml.bind.annotation.XmlRootElement; + +import org.onap.dmaap.dbcapi.service.DmaapService; + + +@XmlRootElement +public class Topic extends DmaapObject { + + private String fqtn; + private String topicName; + private String topicDescription; + private String tnxEnabled; + private String owner; + private String formatUuid; + private ReplicationType replicationCase; + private String globalMrURL; // optional: URL of global MR to replicate to/from + + private ArrayList<MR_Client> clients; + + + + private static Dmaap dmaap = new DmaapService().getDmaap(); + + // + // utility function to generate the FQTN of a topic + public static String genFqtn( String name ) { + CharSequence signal = "."; + String ret; + if ( name.contains( signal )) { + // presence of a dot indicates the name is already fully qualified + ret = name; + } else { + ret = dmaap.getTopicNsRoot() + "." + dmaap.getDmaapName() + "." + name; + } + return ret; + } + + + + public Topic() { + super(); + this.clients = new ArrayList<MR_Client>(); + this.lastMod = new Date(); + this.replicationCase = ReplicationType.Validator("none"); + this.setLastMod(); + logger.debug( "Topic constructor " + this.lastMod ); + } + public Topic(String fqtn, String topicName, String topicDescription, + String tnxEnabled, String owner) { + super(); + this.fqtn = fqtn; + this.topicName = topicName; + this.topicDescription = topicDescription; + //this.dcaeLocationName = dcaeLocationName; + this.tnxEnabled = tnxEnabled; + this.owner = owner; + this.setLastMod(); + this.setStatus( DmaapObject_Status.NEW ); + this.replicationCase = ReplicationType.Validator("none"); + logger.debug( "Topic constructor " + this.getLastMod() ); + } + public String getFqtn() { + return fqtn; + } + public void setFqtn(String fqtn) { + this.fqtn = fqtn; + } + public String getTopicName() { + return topicName; + } + public void setTopicName(String topicName) { + this.topicName = topicName; + } + public String getTopicDescription() { + return topicDescription; + } + public void setTopicDescription(String topicDescription) { + this.topicDescription = topicDescription; + } + + public String getTnxEnabled() { + return tnxEnabled; + } + public void setTnxEnabled(String tnxEnabled) { + this.tnxEnabled = tnxEnabled; + } + public String getOwner() { + return owner; + } + public void setOwner(String owner) { + this.owner = owner; + } + + + public void setClients(ArrayList<MR_Client> clients) { + this.clients = clients; + } + + public ArrayList<MR_Client> getClients() { + return clients; + } + + public int getNumClients() { + if ( this.clients == null ) { + return 0; + } + return this.clients.size(); + } + + + + + public String getFormatUuid() { + return formatUuid; + } + + + + public void setFormatUuid(String formatUuid) { + this.formatUuid = formatUuid; + } + + + public ReplicationType getReplicationCase() { + return replicationCase; + } + + + + /* + public void setReplicationCase(String val) { + this.replicationCase = ReplicationType.Validator(val); + } + */ + + public void setReplicationCase(ReplicationType t) { + this.replicationCase = t; + } + + + public String getGlobalMrURL() { + return globalMrURL; + } + + + + public void setGlobalMrURL(String globalMrURL) { + this.globalMrURL = globalMrURL; + } + + + + public String toProvJSON() { + StringBuilder str = new StringBuilder(); + str.append("{ \"topicName\": \""); + str.append( this.getFqtn() ); + str.append( "\", \"topicDescription\": \""); + str.append( this.getTopicDescription()); + str.append( "\", \"partitionCount\": \"2\", \"replicationCount\": \"1\" } "); + logger.info( str.toString() ); + return str.toString(); + } + + public byte[] getBytes() { + return toProvJSON().getBytes(StandardCharsets.UTF_8); + } +} diff --git a/src/main/java/org/onap/dmaap/dbcapi/resources/Authorization.java b/src/main/java/org/onap/dmaap/dbcapi/resources/Authorization.java new file mode 100644 index 0000000..e8b05c6 --- /dev/null +++ b/src/main/java/org/onap/dmaap/dbcapi/resources/Authorization.java @@ -0,0 +1,35 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2017 AT&T 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 java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.lang.annotation.ElementType; + +import javax.ws.rs.NameBinding; + +// @Authorization annotation +@NameBinding +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.METHOD, ElementType.TYPE}) +public @interface Authorization { + +} diff --git a/src/main/java/org/onap/dmaap/dbcapi/resources/AuthorizationFilter.java b/src/main/java/org/onap/dmaap/dbcapi/resources/AuthorizationFilter.java new file mode 100644 index 0000000..d990b09 --- /dev/null +++ b/src/main/java/org/onap/dmaap/dbcapi/resources/AuthorizationFilter.java @@ -0,0 +1,61 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2017 AT&T 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 java.io.IOException; + +import javax.ws.rs.container.ContainerRequestContext; +import javax.ws.rs.container.ContainerRequestFilter; + +import org.onap.dmaap.dbcapi.aaf.authentication.AuthenticationErrorException; +import org.onap.dmaap.dbcapi.service.ApiService; +import org.onap.dmaap.dbcapi.util.DmaapConfig; + + +@Authorization +public class AuthorizationFilter implements ContainerRequestFilter { + + + + @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 ) { + requestContext.abortWith( apiResp.unauthorized( apiResp.getErr().getMessage() ) ); + return ; + } catch ( Exception e ) { + requestContext.abortWith( apiResp.unavailable() ); + return; + } + + + } + +} diff --git a/src/main/java/org/onap/dmaap/dbcapi/resources/BridgeResource.java b/src/main/java/org/onap/dmaap/dbcapi/resources/BridgeResource.java new file mode 100644 index 0000000..5003801 --- /dev/null +++ b/src/main/java/org/onap/dmaap/dbcapi/resources/BridgeResource.java @@ -0,0 +1,116 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2017 AT&T 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 io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; + +import java.util.List; + +import javax.ws.rs.Consumes; +import javax.ws.rs.GET; +import javax.ws.rs.HeaderParam; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.UriInfo; +import javax.ws.rs.core.Response.Status; + +import org.onap.dmaap.dbcapi.aaf.authentication.AuthenticationErrorException; +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.BrTopic; +import org.onap.dmaap.dbcapi.model.DcaeLocation; +import org.onap.dmaap.dbcapi.model.Dmaap; +import org.onap.dmaap.dbcapi.model.MirrorMaker; +import org.onap.dmaap.dbcapi.service.ApiService; +import org.onap.dmaap.dbcapi.service.MirrorMakerService; + +@Path("/bridge") +@Api( value= "bridge", description = "Endpoint for retreiving MR Bridge metrics" ) +@Consumes(MediaType.APPLICATION_JSON) +@Produces(MediaType.APPLICATION_JSON) +@Authorization +public class BridgeResource extends BaseLoggingClass { + + private MirrorMakerService mmService = new MirrorMakerService(); + + @GET + @ApiOperation( value = "return BrTopic details", + notes = "Returns array of `BrTopic` objects.", + response = BrTopic.class) +@ApiResponses( value = { + @ApiResponse( code = 200, message = "Success", response = Dmaap.class), + @ApiResponse( code = 400, message = "Error", response = ApiError.class ) +}) + public Response getBridgedTopics(@QueryParam("source") String source, + @QueryParam("target") String target){ + ApiService check = new ApiService(); + + BrTopic brTopic = new BrTopic(); + + logger.info( "getBridgeTopics():" + " source=" + source + ", target=" + target); +// System.out.println("getBridgedTopics() " + "source=" + source + ", target=" + target ); + if (source != null && target != null) { // get topics between 2 bridged locations + brTopic.setBrSource(source); + brTopic.setBrTarget(target); + MirrorMaker mm = mmService.getMirrorMaker(source, target); + if ( mm != null ) { + brTopic.setTopicCount( mm.getTopicCount() ); + } + + logger.info( "topicCount [2 locations]: " + brTopic.getTopicCount() ); + } + else if (source == null && target == null ) { + List<String> mmList = mmService.getAllMirrorMakers(); + brTopic.setBrSource("all"); + brTopic.setBrTarget("all"); + int totCnt = 0; + for( String key: mmList ) { + int mCnt = 0; + MirrorMaker mm = mmService.getMirrorMaker(key); + if ( mm != null ) { + mCnt = mm.getTopicCount(); + } + logger.info( "Count for "+ key + ": " + mCnt); + totCnt += mCnt; + } + + logger.info( "topicCount [all locations]: " + totCnt ); + brTopic.setTopicCount(totCnt); + + } + else { + + logger.error( "source or target is missing"); + check.setCode(Status.BAD_REQUEST.getStatusCode()); + check.setMessage("Either 2 locations or no location must be provided"); + return check.error(); + } + return check.success(brTopic); + } +} 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 new file mode 100644 index 0000000..8091ac3 --- /dev/null +++ b/src/main/java/org/onap/dmaap/dbcapi/resources/DR_NodeResource.java @@ -0,0 +1,183 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dcae + * ================================================================================ + * Copyright (C) 2017 AT&T 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 io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; + +import java.util.List; + +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +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; + +@Path("/dr_nodes") +@Api( value= "dr_nodes", description = "Endpoint for a Data Router Node server" ) +@Consumes(MediaType.APPLICATION_JSON) +@Produces(MediaType.APPLICATION_JSON) +@Authorization +public class DR_NodeResource extends BaseLoggingClass { + + DR_NodeService dr_nodeService = new DR_NodeService(); + + @GET + @ApiOperation( value = "return DR_Node details", + notes = "Returns array of `DR_Node` object array. Need to add filter by dcaeLocation.", + response = DR_Node.class) + @ApiResponses( value = { + @ApiResponse( code = 200, message = "Success", response = DR_Node.class), + @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); + } + + @POST + @ApiOperation( value = "return DR_Node details", + notes = "create a `DR_Node` in a *dcaeLocation*. Note that multiple `DR_Node`s may exist in the same `dcaeLocation`.", + response = DR_Node.class) + @ApiResponses( value = { + @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(); + + try { + resp.required( "dcaeLocation", node.getDcaeLocationName(), ""); + resp.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(); + } + DR_Node nNode = dr_nodeService.addDr_Node(node, resp.getErr()); + if ( resp.getErr().is2xx()) { + return resp.success(nNode); + } + return resp.error(); + } + + @PUT + @ApiOperation( value = "return DR_Node details", + notes = "Update a single `DR_Node` object.", + response = DR_Node.class) + @ApiResponses( value = { + @ApiResponse( code = 200, message = "Success", response = DR_Node.class), + @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(); + + try { + resp.required( "dcaeLocation", name, ""); + resp.required( "fqdn", node.getFqdn(), ""); + } catch ( RequiredFieldException rfe ) { + return resp.error(); + } + node.setFqdn(name); + DR_Node nNode = dr_nodeService.updateDr_Node(node, resp.getErr()); + if ( resp.getErr().is2xx()) { + return resp.success(nNode); + } + return resp.error(); + } + + @DELETE + @ApiOperation( value = "No Content", + notes = "Delete a single `DR_Node` object.", + response = DR_Node.class) + @ApiResponses( value = { + @ApiResponse( code = 204, message = "Success", response = DR_Node.class), + @ApiResponse( code = 400, message = "Error", response = ApiError.class ) + }) + @Path("/{fqdn}") + public Response deleteDr_Node( + @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); + } + return resp.error(); + } + + @GET + @ApiOperation( value = "return DR_Node details", + notes = "Retrieve a single `DR_Node` object.", + response = DR_Node.class) + @ApiResponses( value = { + @ApiResponse( code = 200, message = "Success", response = DR_Node.class), + @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); + } + return resp.error(); + } +} 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 new file mode 100644 index 0000000..06319de --- /dev/null +++ b/src/main/java/org/onap/dmaap/dbcapi/resources/DR_PubResource.java @@ -0,0 +1,241 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2017 AT&T 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 io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +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_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; + + +@Path("/dr_pubs") +@Api( value= "dr_pubs", description = "Endpoint for a Data Router client that implements a Publisher" ) +@Consumes(MediaType.APPLICATION_JSON) +@Produces(MediaType.APPLICATION_JSON) +@Authorization +public class DR_PubResource extends BaseLoggingClass { + + DR_PubService dr_pubService = new DR_PubService(); + + @GET + @ApiOperation( value = "return DR_Pub details", + notes = "Returns array of `DR_Pub` objects. Add filter for feedId.", + response = DR_Pub.class) + @ApiResponses( value = { + @ApiResponse( code = 200, message = "Success", response = DR_Pub.class), + @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); + } + + @POST + @ApiOperation( value = "return DR_Pub details", + notes = "create a DR Publisher in the specified environment.", + response = DR_Pub.class) + @ApiResponses( value = { + @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(); + + logger.info( "Entry: POST /dr_pubs"); + + try { + resp.required( "feedId", pub.getFeedId(), ""); + resp.required( "dcaeLocationName", pub.getDcaeLocationName(), ""); + } catch ( RequiredFieldException rfe ) { + logger.debug( resp.getErr().toString() ); + return resp.error(); + } + + FeedService feeds = new FeedService(); + Feed fnew = feeds.getFeed( pub.getFeedId(), resp.getErr() ); + if ( fnew == null ) { + logger.info( "Specified feed " + pub.getFeedId() + " not known to Bus Controller"); + return resp.error(); + } + + ArrayList<DR_Pub> pubs = fnew.getPubs(); + logger.info( "num existing pubs before = " + pubs.size() ); + + logger.info( "update feed"); + pub.setNextPubId(); + if ( pub.getUsername() == null ) { + pub.setRandomUserName(); + } + if ( pub.getUserpwd() == null ) { + pub.setRandomPassword(); + } + pubs.add( pub ); + fnew.setPubs(pubs); + fnew = feeds.updateFeed( fnew, resp.getErr() ); + + if ( ! resp.getErr().is2xx()) { + return resp.error(); + } + 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); + } + + @PUT + @ApiOperation( value = "return DR_Pub details", + notes = "update a DR Publisher in the specified environment. Update a `DR_Pub` object by pubId", + response = DR_Pub.class) + @ApiResponses( value = { + @ApiResponse( code = 200, message = "Success", response = DR_Pub.class), + @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(); + + logger.info( "Entry: PUT /dr_pubs"); + pub.setPubId(name); + DR_Pub res = dr_pubService.updateDr_Pub(pub); + return resp.success(res); + } + + @DELETE + @ApiOperation( value = "return DR_Pub details", + notes = "delete a DR Publisher in the specified environment. Delete a `DR_Pub` object by pubId", + response = DR_Pub.class) + @ApiResponses( value = { + @ApiResponse( code = 204, message = "Success", response = DR_Pub.class), + @ApiResponse( code = 400, message = "Error", response = ApiError.class ) + }) + @Path("/{pubId}") + public Response deleteDr_Pub( + @PathParam("pubId") String id + ){ + + ApiService resp = new ApiService(); + + try { + resp.required( "pubId", id, ""); + } catch ( RequiredFieldException rfe ) { + return resp.error(); + } + + DR_Pub pub = dr_pubService.getDr_Pub( id, resp.getErr() ); + if ( ! resp.getErr().is2xx()) { + return resp.error(); + } + FeedService feeds = new FeedService(); + Feed fnew = feeds.getFeed( pub.getFeedId(), resp.getErr() ); + if ( fnew == null ) { + logger.info( "Specified feed " + pub.getFeedId() + " not known to Bus Controller"); + return resp.error(); + } + 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(); + } + + for( Iterator<DR_Pub> i = pubs.iterator(); i.hasNext(); ) { + DR_Pub listItem = i.next(); + if ( listItem.getPubId().equals(id)) { + pubs.remove( listItem ); + } + } + fnew.setPubs(pubs); + fnew = feeds.updateFeed( fnew, resp.getErr() ); + if ( ! resp.getErr().is2xx()) { + return resp.error(); + } + + dr_pubService.removeDr_Pub(id, resp.getErr() ); + if ( ! resp.getErr().is2xx()) { + return resp.error(); + } + return resp.success(Status.NO_CONTENT.getStatusCode(), null); + } + + @GET + @ApiOperation( value = "return DR_Pub details", + notes = "returns a DR Publisher in the specified environment. Gets a `DR_Pub` object by pubId", + response = DR_Pub.class) + @ApiResponses( value = { + @ApiResponse( code = 200, message = "Success", response = DR_Pub.class), + @ApiResponse( code = 400, message = "Error", response = ApiError.class ) + }) + @Path("/{pubId}") + public Response get( + @PathParam("pubId") String id + ) { + ApiService resp = new ApiService(); + + try { + resp.required( "feedId", id, ""); + } catch ( RequiredFieldException rfe ) { + return resp.error(); + } + + DR_Pub pub = dr_pubService.getDr_Pub( id, resp.getErr() ); + if ( ! resp.getErr().is2xx()) { + resp.getErr(); + } + return resp.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 new file mode 100644 index 0000000..03a8e2f --- /dev/null +++ b/src/main/java/org/onap/dmaap/dbcapi/resources/DR_SubResource.java @@ -0,0 +1,227 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2017 AT&T 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 io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; + +import java.util.ArrayList; +import java.util.List; + +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +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_Pub; +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; + + +@Path("/dr_subs") +@Api( value= "dr_subs", description = "Endpoint for a Data Router client that implements a Subscriber" ) +@Consumes(MediaType.APPLICATION_JSON) +@Produces(MediaType.APPLICATION_JSON) +@Authorization +public class DR_SubResource extends BaseLoggingClass { + + @GET + @ApiOperation( value = "return DR_Sub details", + notes = "Returns array of `DR_Sub` objects. Add filter for feedId.", + response = DR_Sub.class) + @ApiResponses( value = { + @ApiResponse( code = 200, message = "Success", response = DR_Pub.class), + @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); + } + + @POST + @ApiOperation( value = "return DR_Sub details", + notes = "Create a `DR_Sub` object. ", + response = DR_Sub.class) + @ApiResponses( value = { + @ApiResponse( code = 200, message = "Success", response = DR_Pub.class), + @ApiResponse( code = 400, message = "Error", response = ApiError.class ) + }) + public Response addDr_Sub( + DR_Sub sub + ) { + + ApiService resp = new ApiService(); + + try { + resp.required( "feedId", sub.getFeedId(), ""); + resp.required( "dcaeLocationName", sub.getDcaeLocationName(), ""); + + } catch ( RequiredFieldException rfe ) { + logger.debug( resp.toString() ); + return resp.error(); + } + + FeedService feeds = new FeedService(); + Feed fnew = feeds.getFeed( sub.getFeedId(), resp.getErr() ); + if ( fnew == null ) { + logger.warn( "Specified feed " + sub.getFeedId() + " not known to Bus Controller"); + resp.setCode(Status.NOT_FOUND.getStatusCode()); + return resp.error(); + } + + 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(); + } + subs.add( snew ); + logger.info( "num existing subs after = " + subs.size() ); + + fnew.setSubs(subs); + logger.info( "update feed"); + //feeds.updateFeed( fnew, err ); + + return resp.success(Status.CREATED.getStatusCode(), snew); + + } + + @PUT + @ApiOperation( value = "return DR_Sub details", + notes = "Update a `DR_Sub` object, selected by subId", + response = DR_Sub.class) + @ApiResponses( value = { + @ApiResponse( code = 200, message = "Success", response = DR_Pub.class), + @ApiResponse( code = 400, message = "Error", response = ApiError.class ) + }) + @Path("/{subId}") + public Response updateDr_Sub( + @PathParam("subId") String name, + DR_Sub sub + ) { + + ApiService resp = new ApiService(); + + try { + resp.required( "subId", name, ""); + resp.required( "feedId", sub.getFeedId(), ""); + resp.required( "dcaeLocationName", sub.getDcaeLocationName(), ""); + + } catch ( RequiredFieldException rfe ) { + logger.debug( resp.toString() ); + return resp.error(); + } + FeedService feeds = new FeedService(); + Feed fnew = feeds.getFeed( sub.getFeedId(), resp.getErr() ); + if ( fnew == null ) { + logger.warn( "Specified feed " + sub.getFeedId() + " not known to Bus Controller"); + return resp.error(); + } + + DR_SubService dr_subService = new DR_SubService(); + sub.setSubId(name); + DR_Sub nsub = dr_subService.updateDr_Sub(sub, resp.getErr() ); + if ( nsub != null && nsub.isStatusValid() ) { + return resp.success(nsub); + } + return resp.error(); + } + + @DELETE + @ApiOperation( value = "return DR_Sub details", + notes = "Delete a `DR_Sub` object, selected by subId", + response = DR_Sub.class) + @ApiResponses( value = { + @ApiResponse( code = 200, message = "Success", response = DR_Pub.class), + @ApiResponse( code = 400, message = "Error", response = ApiError.class ) + }) + @Path("/{subId}") + public Response deleteDr_Sub( + @PathParam("subId") String id + ){ + + ApiService resp = new ApiService(); + + try { + resp.required( "subId", id, ""); + } catch ( RequiredFieldException rfe ) { + logger.debug( resp.toString() ); + return resp.error(); + } + DR_SubService dr_subService = new DR_SubService(); + dr_subService.removeDr_Sub(id, resp.getErr() ); + if ( ! resp.getErr().is2xx() ) { + return resp.error(); + } + return resp.success(Status.NO_CONTENT.getStatusCode(), null ); + } + + @GET + @ApiOperation( value = "return DR_Sub details", + notes = "Retrieve a `DR_Sub` object, selected by subId", + response = DR_Sub.class) + @ApiResponses( value = { + @ApiResponse( code = 200, message = "Success", response = DR_Pub.class), + @ApiResponse( code = 400, message = "Error", response = ApiError.class ) + }) + @Path("/{subId}") + public Response get( + @PathParam("subId") String id + ) { + ApiService resp = new ApiService(); + + try { + resp.required( "subId", id, ""); + } catch ( RequiredFieldException rfe ) { + logger.debug( resp.toString() ); + return resp.error(); + } + DR_SubService dr_subService = new DR_SubService(); + DR_Sub sub = dr_subService.getDr_Sub( id, resp.getErr() ); + if ( sub != null && sub.isStatusValid() ) { + return resp.success(sub); + } + return resp.error(); + } +} diff --git a/src/main/java/org/onap/dmaap/dbcapi/resources/DcaeLocationResource.java b/src/main/java/org/onap/dmaap/dbcapi/resources/DcaeLocationResource.java new file mode 100644 index 0000000..25e6f3a --- /dev/null +++ b/src/main/java/org/onap/dmaap/dbcapi/resources/DcaeLocationResource.java @@ -0,0 +1,180 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2017 AT&T 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 io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; + +import java.util.List; + +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +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.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.model.Dmaap; +import org.onap.dmaap.dbcapi.service.ApiService; +import org.onap.dmaap.dbcapi.service.DcaeLocationService; + + +@Path("/dcaeLocations") +@Api( value= "dcaeLocations", description = "an OpenStack tenant purposed for OpenDCAE (i.e. where OpenDCAE components might be deployed)" ) +@Consumes(MediaType.APPLICATION_JSON) +@Produces(MediaType.APPLICATION_JSON) +@Authorization +public class DcaeLocationResource extends BaseLoggingClass { + static final Logger logger = Logger.getLogger(DcaeLocationResource.class); + DcaeLocationService locationService = new DcaeLocationService(); + + @GET + @ApiOperation( value = "return dcaeLocation details", + notes = "Returns array of `dcaeLocation` objects. All objects managed by DMaaP are deployed in some `dcaeLocation` which is a unique identifier for an *OpenStack* tenant purposed for a *dcaeLayer* (ecomp or edge).", + response = DcaeLocation.class) + @ApiResponses( value = { + @ApiResponse( code = 200, message = "Success", response = Dmaap.class), + @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); + } + + @POST + @ApiOperation( value = "return dcaeLocation details", + notes = "Create some `dcaeLocation` which is a unique identifier for an *OpenStack* tenant purposed for a *dcaeLayer* (ecomp or edge).", + response = DcaeLocation.class) + @ApiResponses( value = { + @ApiResponse( code = 200, message = "Success", response = Dmaap.class), + @ApiResponse( code = 400, message = "Error", response = ApiError.class ) + }) + public Response addDcaeLocation( + DcaeLocation location + ) { + ApiService check = new ApiService(); + + if ( locationService.getDcaeLocation(location.getDcaeLocationName()) != null ) { + + check.setCode(Status.CONFLICT.getStatusCode()); + check.setMessage("dcaeLocation already exists"); + check.setFields("dcaeLocation"); + + return check.error(); + + } + DcaeLocation loc = locationService.addDcaeLocation(location); + return check.success(Status.CREATED.getStatusCode(), loc); + } + + @PUT + @ApiOperation( value = "return dcaeLocation details", + notes = "update the openStackAvailabilityZone of a dcaeLocation", + response = DcaeLocation.class) + @ApiResponses( value = { + @ApiResponse( code = 200, message = "Success", response = Dmaap.class), + @ApiResponse( code = 400, message = "Error", response = ApiError.class ) + }) + @Path("/{locationName}") + public Response updateDcaeLocation( + @PathParam("locationName") String name, + DcaeLocation location + ) { + ApiService check = new ApiService(); + + 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(); + + + } + DcaeLocation loc = locationService.updateDcaeLocation(location); + return check.success(Status.CREATED.getStatusCode(), loc ); + } + + @DELETE + @ApiOperation( value = "return dcaeLocation details", notes = "delete a dcaeLocation", response = Dmaap.class) + @ApiResponses( value = { + @ApiResponse( code = 204, message = "Success", response = Dmaap.class), + @ApiResponse( code = 400, message = "Error", response = ApiError.class ) + }) + @Path("/{locationName}") + public Response deleteDcaeLocation( + @PathParam("locationName") String name + ){ + ApiService check = new ApiService(); + + locationService.removeDcaeLocation(name); + return check.success(Status.NO_CONTENT.getStatusCode(), null); + } + + @GET + @ApiOperation( value = "return dcaeLocation details", notes = "Returns a specific `dcaeLocation` object with specified tag", response = Dmaap.class) + @ApiResponses( value = { + @ApiResponse( code = 200, message = "Success", response = Dmaap.class), + @ApiResponse( code = 400, message = "Error", response = ApiError.class ) + }) + @Path("/{locationName}") + public Response getDcaeLocation( + @PathParam("locationName") String name + ) { + ApiService check = new ApiService(); + + DcaeLocation loc = locationService.getDcaeLocation( name ); + if ( loc == null ) { + ApiError err = new ApiError(); + + err.setCode(Status.NOT_FOUND.getStatusCode()); + err.setMessage("dcaeLocation does not exist"); + err.setFields("dcaeLocation"); + + return check.error(); + + + } + + return check.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 new file mode 100644 index 0000000..bd30055 --- /dev/null +++ b/src/main/java/org/onap/dmaap/dbcapi/resources/DmaapResource.java @@ -0,0 +1,129 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2017 AT&T 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========================================================= + */ + +// +// $Id$ + +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 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; +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" ) +@Consumes(MediaType.APPLICATION_JSON) +@Produces(MediaType.APPLICATION_JSON) +@Authorization +public class DmaapResource extends BaseLoggingClass { + + + DmaapService dmaapService = new DmaapService(); + + @GET + @ApiOperation( value = "return dmaap details", notes = "returns the `dmaap` object, which contains system wide configuration settings", response = Dmaap.class) + @ApiResponses( value = { + @ApiResponse( code = 200, message = "Success", response = Dmaap.class), + @ApiResponse( code = 400, message = "Error", response = ApiError.class ) + }) + + public Response getDmaap(@Context UriInfo uriInfo) { + ApiService check = new ApiService(); + + Dmaap d = dmaapService.getDmaap(); + return check.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 = { + @ApiResponse( code = 200, message = "Success", response = Dmaap.class), + @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(), "" ); + } catch( RequiredFieldException rfe ) { + return check.error(); + } + + Dmaap d = dmaapService.addDmaap(obj); + if ( d == null ) { + return check.notFound(); + + } + + return check.success(d); + } + + @PUT + @ApiOperation( value = "return dmaap details", notes = "Update system settings for *dcaeEnvironment*.", response = Dmaap.class) + @ApiResponses( value = { + @ApiResponse( code = 200, message = "Success", response = Dmaap.class), + @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(), "" ); + } catch( RequiredFieldException rfe ) { + return check.error(); + } + Dmaap d = dmaapService.updateDmaap(obj); + if ( d != null ) { + return check.success(d); + } else { + return check.notFound(); + } + } + + +} diff --git a/src/main/java/org/onap/dmaap/dbcapi/resources/FeedResource.java b/src/main/java/org/onap/dmaap/dbcapi/resources/FeedResource.java new file mode 100644 index 0000000..361491a --- /dev/null +++ b/src/main/java/org/onap/dmaap/dbcapi/resources/FeedResource.java @@ -0,0 +1,255 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2017 AT&T 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 io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; + +import java.util.List; + +import javax.jws.WebParam; +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.HeaderParam; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.Context; +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 javax.ws.rs.core.UriInfo; + +import org.apache.log4j.Logger; + + + + + + + + + + + + + + + + + + + +import org.onap.dmaap.dbcapi.aaf.authentication.AuthenticationErrorException; +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.DR_Pub; +import org.onap.dmaap.dbcapi.model.DR_Sub; +import org.onap.dmaap.dbcapi.model.Feed; +import org.onap.dmaap.dbcapi.model.Topic; +import org.onap.dmaap.dbcapi.model.DmaapObject.DmaapObject_Status; +import org.onap.dmaap.dbcapi.service.ApiService; +import org.onap.dmaap.dbcapi.service.FeedService; + + +@Path("/feeds") +@Api( value= "Feeds", description = "Endpoint for a Data Router Feed" ) +@Consumes(MediaType.APPLICATION_JSON) +@Produces(MediaType.APPLICATION_JSON) +@Authorization +public class FeedResource extends BaseLoggingClass { + + @GET + @ApiOperation( value = "return Feed details", + notes = "Returns array of `Feed` objects.", + response = Feed.class) + @ApiResponses( value = { + @ApiResponse( code = 200, message = "Success", response = DR_Pub.class), + @ApiResponse( code = 400, message = "Error", response = ApiError.class ) + }) + public Response getFeeds() { + + ApiService resp = new ApiService(); + + FeedService feedService = new FeedService(); + List<Feed> nfeeds = feedService.getAllFeeds(); + GenericEntity<List<Feed>> list = new GenericEntity<List<Feed>>(nfeeds) { + }; + return resp.success(list); + } + + + + @POST + @ApiOperation( value = "return Feed details", + notes = "Create a of `Feed` object.", + response = Feed.class) + @ApiResponses( value = { + @ApiResponse( code = 200, message = "Success", response = DR_Pub.class), + @ApiResponse( code = 400, message = "Error", response = ApiError.class ) + }) + public Response addFeed( + @WebParam(name = "feed") Feed feed + ) { + + ApiService resp = new ApiService(); + + try { + resp.required( "feedName", feed.getFeedName(), ""); + resp.required( "feedVersion", feed.getFeedVersion(), ""); + resp.required( "owner", feed.getOwner(), "" ); + resp.required( "asprClassification", feed.getAsprClassification(), "" ); + } catch ( RequiredFieldException rfe ) { + logger.debug( resp.toString() ); + return resp.error(); + } + + FeedService feedService = new FeedService(); + Feed nfeed = feedService.getFeedByName( feed.getFeedName(), feed.getFeedVersion(), resp.getErr() ); + if ( nfeed == null ) { + nfeed = feedService.addFeed( feed, resp.getErr() ); + if ( nfeed != null ) { + return resp.success(nfeed); + } else { + logger.error( "Unable to create: " + feed.getFeedName() + ":" + feed.getFeedVersion()); + + return resp.error(); + } + } else if ( nfeed.getStatus() == DmaapObject_Status.DELETED ) { + nfeed = feedService.updateFeed(nfeed, resp.getErr()); + if ( nfeed != null ) { + return resp.success(nfeed); + } else { + logger.info( "Unable to update: " + feed.getFeedName() + ":" + feed.getFeedVersion()); + + return resp.error(); + } + } + + resp.setCode(Status.CONFLICT.getStatusCode()); + return resp.error(); + } + + @PUT + @ApiOperation( value = "return Feed details", + notes = "Update a `Feed` object, specified by id.", + response = Feed.class) + @ApiResponses( value = { + @ApiResponse( code = 200, message = "Success", response = DR_Pub.class), + @ApiResponse( code = 400, message = "Error", response = ApiError.class ) + }) + @Path("/{id}") + public Response updateFeed( + @PathParam("id") String id, + @WebParam(name = "feed") Feed feed + ) { + + FeedService feedService = new FeedService(); + ApiService resp = new ApiService(); + + try { + resp.required( "feedId", id, ""); + } catch ( RequiredFieldException rfe ) { + logger.debug( resp.toString() ); + return resp.error(); + } + + Feed nfeed = feedService.getFeed( id, resp.getErr() ); + if ( nfeed == null || nfeed.getStatus() == DmaapObject_Status.DELETED ) { + return resp.notFound(); + } + + // we assume there is no updates allowed for pubs and subs objects via this api... + // need to update any fields supported by PUT but preserve original field values. + nfeed.setSuspended(feed.isSuspended()); + nfeed.setFeedDescription(feed.getFeedDescription()); + nfeed.setFormatUuid(feed.getFormatUuid()); + + nfeed = feedService.updateFeed(nfeed, resp.getErr()); + if ( nfeed != null ) { + return resp.success(nfeed); + } else { + logger.info( "Unable to update: " + feed.getFeedName() + ":" + feed.getFeedVersion()); + + return resp.error(); + } + } + + @DELETE + @ApiOperation( value = "return Feed details", + notes = "Delete a `Feed` object, specified by id.", + response = Feed.class) + @ApiResponses( value = { + @ApiResponse( code = 204, message = "Success", response = DR_Pub.class), + @ApiResponse( code = 400, message = "Error", response = ApiError.class ) + }) + @Path("/{id}") + public Response deleteFeed( + @PathParam("id") String id + ){ + ApiService resp = new ApiService(); + + logger.debug( "Entry: DELETE " + id); + FeedService feedService = new FeedService(); + Feed nfeed = feedService.getFeed( id, resp.getErr() ); + if ( nfeed == null ) { + resp.setCode(Status.NOT_FOUND.getStatusCode()); + return resp.error(); + } + nfeed = feedService.removeFeed( nfeed, resp.getErr() ); + if ( nfeed == null || nfeed.getStatus() == DmaapObject_Status.DELETED ) { + return resp.success(Status.NO_CONTENT.getStatusCode(), null); + } + logger.info( "Unable to delete: " + id + ":" + nfeed.getFeedVersion()); + + return resp.error(); + } + + @GET + @ApiOperation( value = "return Feed details", + notes = "Retrieve a `Feed` object, specified by id.", + response = Feed.class) + @ApiResponses( value = { + @ApiResponse( code = 200, message = "Success", response = DR_Pub.class), + @ApiResponse( code = 400, message = "Error", response = ApiError.class ) + }) + @Path("/{id}") + public Response getFeed( + @PathParam("id") String id + ) { + ApiService resp = new ApiService(); + + FeedService feedService = new FeedService(); + Feed nfeed = feedService.getFeed( id, resp.getErr() ); + if ( nfeed == null ) { + resp.setCode(Status.NOT_FOUND.getStatusCode()); + return resp.error(); + } + return resp.success(nfeed); + } +} 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 new file mode 100644 index 0000000..8f6a506 --- /dev/null +++ b/src/main/java/org/onap/dmaap/dbcapi/resources/MR_ClientResource.java @@ -0,0 +1,232 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2017 AT&T 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 io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; + +import java.util.List; + +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +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_Pub; +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; + + +@Path("/mr_clients") +@Api( value= "MR_Clients", description = "Endpoint for a Message Router Client that implements a Publisher or a Subscriber" ) +@Consumes(MediaType.APPLICATION_JSON) +@Produces(MediaType.APPLICATION_JSON) +@Authorization +public class MR_ClientResource extends BaseLoggingClass { + + private MR_ClientService mr_clientService = new MR_ClientService(); + + @GET + @ApiOperation( value = "return MR_Client details", + notes = "Returns array of `MR_Client` objects.", + response = MR_Client.class) + @ApiResponses( value = { + @ApiResponse( code = 200, message = "Success", response = DR_Pub.class), + @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); + } + + @POST + @ApiOperation( value = "return MR_Client details", + notes = "Create a `MR_Client` object.", + response = MR_Client.class) + @ApiResponses( value = { + @ApiResponse( code = 200, message = "Success", response = DR_Pub.class), + @ApiResponse( code = 400, message = "Error", response = ApiError.class ) + }) + public Response addMr_Client( + MR_Client client + ) { + ApiService resp = new ApiService(); + + try { + resp.required( "fqtn", client.getFqtn(), ""); + resp.required( "dcaeLocationName", client.getDcaeLocationName(), ""); + resp.required( "clientRole", client.getClientRole(), "" ); + resp.required( "action", client.getAction(), ""); + + } catch ( RequiredFieldException rfe ) { + logger.debug( resp.toString() ); + return resp.error(); + } + MR_ClusterService clusters = new MR_ClusterService(); + + MR_Cluster cluster = clusters.getMr_Cluster(client.getDcaeLocationName(), resp.getErr()); + 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(); + } + 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(); + } + TopicService topics = new TopicService(); + + Topic t = topics.getTopic(client.getFqtn(), resp.getErr() ); + if ( t == null ) { + return resp.error(); + } + 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); + } + else { + return resp.error(); + } + } + + @PUT + @ApiOperation( value = "return MR_Client details", + notes = "Update a `MR_Client` object, specified by clientId", + response = MR_Client.class) + @ApiResponses( value = { + @ApiResponse( code = 200, message = "Success", response = DR_Pub.class), + @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(); + + try { + resp.required( "fqtn", client.getFqtn(), ""); + resp.required( "dcaeLocationName", client.getDcaeLocationName(), ""); + resp.required( "clientRole", client.getClientRole(), "" ); + resp.required( "action", client.getAction(), ""); + + } catch ( RequiredFieldException rfe ) { + logger.debug( resp.toString() ); + return resp.error(); + } + client.setMrClientId(clientId); + MR_Client nClient = mr_clientService.updateMr_Client(client, resp.getErr() ); + if ( resp.getErr().is2xx()) { + return Response.ok(nClient) + .build(); + } + return Response.status(resp.getErr().getCode()) + .entity( resp.getErr() ) + .build(); + } + + @DELETE + @ApiOperation( value = "return MR_Client details", + notes = "Delete a `MR_Client` object, specified by clientId", + response = MR_Client.class) + @ApiResponses( value = { + @ApiResponse( code = 204, message = "Success", response = DR_Pub.class), + @ApiResponse( code = 400, message = "Error", response = ApiError.class ) + }) + @Path("/{subId}") + public Response deleteMr_Client( + @PathParam("subId") String id + ){ + ApiService resp = new ApiService(); + + try { + resp.required( "clientId", id, ""); + } catch ( RequiredFieldException rfe ) { + logger.debug( resp.toString() ); + return resp.error(); + } + mr_clientService.removeMr_Client(id, true, resp.getErr() ); + if ( resp.getErr().is2xx()) { + return resp.success(Status.NO_CONTENT.getStatusCode(), null); + } + + return resp.error(); + } + + @GET + @ApiOperation( value = "return MR_Client details", + notes = "Retrieve a `MR_Client` object, specified by clientId", + response = MR_Client.class) + @ApiResponses( value = { + @ApiResponse( code = 200, message = "Success", response = DR_Pub.class), + @ApiResponse( code = 400, message = "Error", response = ApiError.class ) + }) + @Path("/{subId}") + public Response test( + @PathParam("subId") String id + ) { + ApiService resp = new ApiService(); + + try { + resp.required( "clientId", id, ""); + } catch ( RequiredFieldException rfe ) { + logger.debug( resp.toString() ); + return resp.error(); + } + MR_Client nClient = mr_clientService.getMr_Client( id, resp.getErr() ); + if ( resp.getErr().is2xx()) { + return resp.success(nClient); + } + return resp.error(); + } +} 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 new file mode 100644 index 0000000..41aaead --- /dev/null +++ b/src/main/java/org/onap/dmaap/dbcapi/resources/MR_ClusterResource.java @@ -0,0 +1,187 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2017 AT&T 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 io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; + +import java.util.List; + +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +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_Pub; +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; + + +@Path("/mr_clusters") +@Api( value= "MR_Clusters", description = "Endpoint for a Message Router servers in a Cluster configuration" ) +@Consumes(MediaType.APPLICATION_JSON) +@Produces(MediaType.APPLICATION_JSON) +@Authorization +public class MR_ClusterResource extends BaseLoggingClass { + + MR_ClusterService mr_clusterService = new MR_ClusterService(); + MR_ClientService mr_clients = new MR_ClientService(); + + @GET + @ApiOperation( value = "return MR_Cluster details", + notes = "Returns array of `MR_Cluster` objects.", + response = MR_Cluster.class) + @ApiResponses( value = { + @ApiResponse( code = 200, message = "Success", response = DR_Pub.class), + @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); + } + + @POST + @ApiOperation( value = "return MR_Cluster details", + notes = "Create an `MR_Cluster` object.", + response = MR_Cluster.class) + @ApiResponses( value = { + @ApiResponse( code = 200, message = "Success", response = DR_Pub.class), + @ApiResponse( code = 400, message = "Error", response = ApiError.class ) + }) + public Response addMr_Cluster( + MR_Cluster cluster + ) { + ApiService resp = new ApiService(); + + try { + resp.required( "dcaeLocationName", cluster.getDcaeLocationName(), "" ); + resp.required( "fqdn", cluster.getFqdn(), "" ); + } catch( RequiredFieldException rfe ) { + return resp.error(); + } + MR_Cluster mrc = mr_clusterService.addMr_Cluster(cluster, resp.getErr() ); + if ( mrc != null && mrc.isStatusValid() ) { + return resp.success(Status.CREATED.getStatusCode(), mrc); + } + return resp.error(); + + } + + @PUT + @ApiOperation( value = "return MR_Cluster details", + notes = "Update an `MR_Cluster` object, specified by clusterId.", + response = MR_Cluster.class) + @ApiResponses( value = { + @ApiResponse( code = 200, message = "Success", response = DR_Pub.class), + @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(); + + try { + resp.required( "fqdn", clusterId, "" ); + resp.required( "dcaeLocationName", cluster.getDcaeLocationName(), "" ); + } catch( RequiredFieldException rfe ) { + return resp.error(); + } + cluster.setDcaeLocationName(clusterId); + MR_Cluster mrc = mr_clusterService.updateMr_Cluster(cluster, resp.getErr() ); + if ( mrc != null && mrc.isStatusValid() ) { + return resp.success(Status.CREATED.getStatusCode(), mrc); + } + return resp.error(); + } + + @DELETE + @ApiOperation( value = "return MR_Cluster details", + notes = "Delete an `MR_Cluster` object, specified by clusterId.", + response = MR_Cluster.class) + @ApiResponses( value = { + @ApiResponse( code = 204, message = "Success", response = DR_Pub.class), + @ApiResponse( code = 400, message = "Error", response = ApiError.class ) + }) + @Path("/{clusterId}") + public Response deleteMr_Cluster( + @PathParam("clusterId") String id + ){ + ApiService resp = new ApiService(); + + try { + resp.required( "fqdn", id, "" ); + } catch( RequiredFieldException rfe ) { + return resp.error(); + } + mr_clusterService.removeMr_Cluster(id, resp.getErr() ); + if ( resp.getErr().is2xx()) { + return resp.success(Status.NO_CONTENT.getStatusCode(), null); + } + return resp.error(); + } + + @GET + @ApiOperation( value = "return MR_Cluster details", + notes = "Retrieve an `MR_Cluster` object, specified by clusterId.", + response = MR_Cluster.class) + @ApiResponses( value = { + @ApiResponse( code = 200, message = "Success", response = DR_Pub.class), + @ApiResponse( code = 400, message = "Error", response = ApiError.class ) + }) + @Path("/{clusterId}") + public Response getMR_Cluster( + @PathParam("clusterId") String id + ) { + ApiService resp = new ApiService(); + + try { + resp.required( "dcaeLocationName", id, "" ); + } catch( RequiredFieldException rfe ) { + return resp.error(); + } + MR_Cluster mrc = mr_clusterService.getMr_Cluster( id, resp.getErr() ); + if ( mrc != null && mrc.isStatusValid() ) { + return resp.success(Status.CREATED.getStatusCode(), mrc); + } + return resp.error(); + } +} diff --git a/src/main/java/org/onap/dmaap/dbcapi/resources/RequiredFieldException.java b/src/main/java/org/onap/dmaap/dbcapi/resources/RequiredFieldException.java new file mode 100644 index 0000000..74af356 --- /dev/null +++ b/src/main/java/org/onap/dmaap/dbcapi/resources/RequiredFieldException.java @@ -0,0 +1,30 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2017 AT&T 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; + +public class RequiredFieldException extends Exception { + + /** + * + */ + private static final long serialVersionUID = 1L; + +} diff --git a/src/main/java/org/onap/dmaap/dbcapi/resources/TopicResource.java b/src/main/java/org/onap/dmaap/dbcapi/resources/TopicResource.java new file mode 100644 index 0000000..0f99fb6 --- /dev/null +++ b/src/main/java/org/onap/dmaap/dbcapi/resources/TopicResource.java @@ -0,0 +1,191 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2017 AT&T 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 io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; + +import java.util.List; + +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +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_Pub; +import org.onap.dmaap.dbcapi.model.ReplicationType; +import org.onap.dmaap.dbcapi.model.Topic; +import org.onap.dmaap.dbcapi.service.ApiService; +import org.onap.dmaap.dbcapi.service.TopicService; + +@Path("/topics") +@Api( value= "topics", description = "Endpoint for retreiving MR Topics" ) +@Consumes(MediaType.APPLICATION_JSON) +@Produces(MediaType.APPLICATION_JSON) +@Authorization +public class TopicResource extends BaseLoggingClass { + + TopicService mr_topicService = new TopicService(); + + @GET + @ApiOperation( value = "return Topic details", + notes = "Returns array of `Topic` objects.", + response = Topic.class) + @ApiResponses( value = { + @ApiResponse( code = 200, message = "Success", response = DR_Pub.class), + @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); + + } + + @POST + @ApiOperation( value = "return Topic details", + notes = "Create `Topic` object.", + response = Topic.class) + @ApiResponses( value = { + @ApiResponse( code = 200, message = "Success", response = DR_Pub.class), + @ApiResponse( code = 400, message = "Error", response = ApiError.class ) + }) + public Response addTopic( + Topic topic + ) { + logger.info( "addTopic request: " + String.valueOf(topic) ); + ApiService check = new ApiService(); + + try { + check.required( "topicName", topic.getTopicName(), "^\\S+$" ); //no white space allowed in topicName + check.required( "topicDescription", topic.getTopicDescription(), "" ); + check.required( "owner", topic.getOwner(), "" ); + } catch( RequiredFieldException rfe ) { + return check.error(); + } + + //String repReq = topic.getReplicationRequest(); + ReplicationType t = topic.getReplicationCase(); + if ( t == null || t == ReplicationType.REPLICATION_NOT_SPECIFIED ) { + topic.setReplicationCase( mr_topicService.reviewTopic(topic)); + } + + topic.setLastMod(); + + Topic mrc = mr_topicService.addTopic(topic, check.getErr()); + if ( mrc != null && mrc.isStatusValid() ) { + return check.success(Status.CREATED.getStatusCode(), mrc); + } + return check.error(); + } + + @PUT + @ApiOperation( value = "return Topic details", + notes = "Update a `Topic` object, identified by topicId", + response = Topic.class) + @ApiResponses( value = { + @ApiResponse( code = 200, message = "Success", response = DR_Pub.class), + @ApiResponse( code = 400, message = "Error", response = ApiError.class ) + }) + @Path("/{topicId}") + public Response updateTopic( + @PathParam("topicId") String topicId + ) { + ApiService check = new ApiService(); + + check.setCode(Status.BAD_REQUEST.getStatusCode()); + check.setMessage( "Method /PUT not supported for /topics"); + + return check.error(); + } + + @DELETE + @ApiOperation( value = "return Topic details", + notes = "Delete a `Topic` object, identified by topicId", + response = Topic.class) + @ApiResponses( value = { + @ApiResponse( code = 204, message = "Success", response = DR_Pub.class), + @ApiResponse( code = 400, message = "Error", response = ApiError.class ) + }) + @Path("/{topicId}") + public Response deleteTopic( + @PathParam("topicId") String id + ){ + ApiService check = new ApiService(); + + try { + check.required( "fqtn", id, "" ); + } catch( RequiredFieldException rfe ) { + return check.error(); + } + + mr_topicService.removeTopic(id, check.getErr()); + if ( check.getErr().is2xx()) { + return check.success(Status.NO_CONTENT.getStatusCode(), null); + } + return check.error(); + } + + + @GET + @ApiOperation( value = "return Topic details", + notes = "Retrieve a `Topic` object, identified by topicId", + response = Topic.class) + @ApiResponses( value = { + @ApiResponse( code = 200, message = "Success", response = DR_Pub.class), + @ApiResponse( code = 400, message = "Error", response = ApiError.class ) + }) + @Path("/{topicId}") + public Response getTopic( + @PathParam("topicId") String id + ) { + logger.info("Entry: /GET " + id); + ApiService check = new ApiService(); + + try { + check.required( "topicName", id, "^\\S+$" ); //no white space allowed in topicName + } catch( RequiredFieldException rfe ) { + return check.error(); + } + Topic mrc = mr_topicService.getTopic( id, check.getErr() ); + if ( mrc == null ) { + return check.error(); + } + return check.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 new file mode 100644 index 0000000..2283ea2 --- /dev/null +++ b/src/main/java/org/onap/dmaap/dbcapi/server/ApplicationConfig.java @@ -0,0 +1,36 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2017 AT&T 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.server; + +import org.glassfish.jersey.server.ResourceConfig; + + + +public class ApplicationConfig extends ResourceConfig { + + /* + * Register JAX-RS application components + */ + public ApplicationConfig() { + + register(org.onap.dmaap.dbcapi.resources.AuthorizationFilter.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 new file mode 100644 index 0000000..4d06310 --- /dev/null +++ b/src/main/java/org/onap/dmaap/dbcapi/server/JettyServer.java @@ -0,0 +1,151 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2017 AT&T 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.server; + + +import java.util.Properties; + +import javax.net.ssl.SSLContext; + +import org.apache.log4j.Logger; +import org.eclipse.jetty.security.SecurityHandler; +import org.eclipse.jetty.server.Connector; +import org.eclipse.jetty.server.HttpConfiguration; +import org.eclipse.jetty.server.HttpConnectionFactory; +import org.eclipse.jetty.server.SecureRequestCustomizer; +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.server.ServerConnector; +import org.eclipse.jetty.server.SslConnectionFactory; +import org.eclipse.jetty.servlet.DefaultServlet; +import org.eclipse.jetty.servlet.ServletContextHandler; +import org.eclipse.jetty.servlet.ServletHolder; +import org.eclipse.jetty.util.ssl.SslContextFactory; + + + + +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; + +import org.onap.dmaap.dbcapi.aaf.database.LoadSchema; +import org.onap.dmaap.dbcapi.logging.BaseLoggingClass; +/** + * A Jetty server which supports: + * - http and https (simultaneously for dev env) + * - REST API context + * - static html pages (for documentation). + */ +public class JettyServer extends BaseLoggingClass { + + public JettyServer( Properties params ) throws Exception { + + Server 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 ); + + // HTTP Server + + HttpConfiguration http_config = new HttpConfiguration(); + http_config.setSecureScheme("https"); + http_config.setSecurePort(sslPort); + http_config.setOutputBufferSize(32768); + + + + ServerConnector httpConnector = new ServerConnector(server, new HttpConnectionFactory(http_config)); + httpConnector.setPort(httpPort); + httpConnector.setIdleTimeout(30000); + + + // HTTPS Server + + HttpConfiguration https_config = new HttpConfiguration(http_config); + https_config.addCustomizer(new SecureRequestCustomizer()); + SslContextFactory sslContextFactory = new SslContextFactory(); + String keystore = params.getProperty("KeyStoreFile", "etc/keystore"); + logger.info( "https Server using keystore at " + keystore ); + String keystorePwd = params.getProperty( "KeyStorePassword", "changeit"); + String keyPwd = params.getProperty("KeyPassword", "changeit"); + + + sslContextFactory.setKeyStorePath(keystore); + sslContextFactory.setKeyStorePassword(keystorePwd); + sslContextFactory.setKeyManagerPassword(keyPwd); + + + ServerConnector sslConnector = null; + if ( sslPort != 0 ) { + 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 ); + logger.info("Starting sslConnector on port " + sslPort + " for https"); + server.setConnectors( new Connector[] { httpConnector, sslConnector }); + } else { + logger.info("NOT starting httpConnector because HttpAllowed param is " + allowHttp ); + logger.info("Starting sslConnector on port " + sslPort + " for https"); + 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 }); + } + } + + // Set context for servlet. This is shared for http and https + ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS); + context.setContextPath("/"); + server.setHandler( context ); + + 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" ); + + // also serve up some static pages... + ServletHolder staticServlet = context.addServlet(DefaultServlet.class,"/*"); + staticServlet.setInitParameter("resourceBase","www"); + staticServlet.setInitParameter("pathInfoOnly","true"); + + try { + + serverLogger.info("Starting jetty server"); + 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); + } finally { + server.destroy(); + } + + } +} diff --git a/src/main/java/org/onap/dmaap/dbcapi/server/Main.java b/src/main/java/org/onap/dmaap/dbcapi/server/Main.java new file mode 100644 index 0000000..1ada428 --- /dev/null +++ b/src/main/java/org/onap/dmaap/dbcapi/server/Main.java @@ -0,0 +1,115 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2017 AT&T 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.server; +import java.net.InetAddress; +import java.util.Properties; +import java.util.UUID; + +import org.onap.dmaap.dbcapi.aaf.authentication.ApiPerms; +import org.onap.dmaap.dbcapi.aaf.database.DatabaseClass; +import org.onap.dmaap.dbcapi.logging.*; +import org.onap.dmaap.dbcapi.model.Dmaap; +import org.onap.dmaap.dbcapi.util.DmaapConfig; +import org.onap.dmaap.dbcapi.util.Singleton; + +import static com.att.eelf.configuration.Configuration.*; + +import org.slf4j.MDC; + +public class Main extends BaseLoggingClass { + + + private Properties parameters; + private static String provFQDN; + + public static String getProvFQDN() { + return provFQDN; + } + public void setProvFQDN(String provFQDN) { + Main.provFQDN = provFQDN; + } + private Main() { + } + public static void main(String[] args) throws Exception { + (new Main()).main(); + } + + private void main() { + + MDC.clear(); + + MDC.put(MDC_SERVICE_INSTANCE_ID, ""); + try { + MDC.put(MDC_SERVER_FQDN, InetAddress.getLocalHost().getHostName()); + MDC.put(MDC_SERVER_IP_ADDRESS, InetAddress.getLocalHost().getHostAddress()); + } catch (Exception e) { + e.printStackTrace(); + } + MDC.put(MDC_INSTANCE_UUID, UUID.randomUUID().toString()); + MDC.put(MDC_ALERT_SEVERITY, "0"); + + + MDC.put(MDC_TARGET_ENTITY, "DCAE"); + + +/* + String msg = "This is a sample {} message to demo EELF logging."; + + appLogger.info( msg, "appLogger.info"); + + auditLogger.auditEvent( msg, "auditLogger.auditEvent"); + errorLogger.error(DmaapbcLogMessageEnum.MESSAGE_SAMPLE_NOARGS); + errorLogger.error(DmaapbcLogMessageEnum.MESSAGE_SAMPLE_ONE_ARG, "errorLogger.error"); + errorLogger.error(DmaapbcLogMessageEnum.MESSAGE_SAMPLE_TWO_ARGS, new Date().toString(), "errorLogger.error" ); + metricsLogger.metricsEvent( msg, "metricsLogger.metricsEvent" ); + debugLogger.debug( msg, "debugLogger.debug"); + + //String log = System.getProperty( "log4j.configuration"); + //if ( log.isEmpty() ) { + // log = "log4j.properties"; + //} + //PropertyConfigurator.configure( log ); + * + */ + appLogger.info("Started."); + parameters = DmaapConfig.getConfig(); + setProvFQDN( parameters.getProperty("ProvFQDN", "ProvFQDN.notset.com")); + + + // for fresh installs, we may come up with no dmaap name so need to have a way for Controller to talk to us + Singleton<Dmaap> dmaapholder = DatabaseClass.getDmaap(); + String name = dmaapholder.get().getDmaapName(); + if ( name == null || name.isEmpty()) { + ApiPerms p = new ApiPerms(); + p.setBootMap(); + } + + + try { + new JettyServer( parameters ); + } catch (Exception e) { + errorLogger.error("Unable to start Jetty " + DmaapConfig.getConfigFileName(), e); + System.exit(1); + } + + } + +} diff --git a/src/main/java/org/onap/dmaap/dbcapi/service/ApiService.java b/src/main/java/org/onap/dmaap/dbcapi/service/ApiService.java new file mode 100644 index 0000000..aab989d --- /dev/null +++ b/src/main/java/org/onap/dmaap/dbcapi/service/ApiService.java @@ -0,0 +1,339 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2017 AT&T 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.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.aaf.authentication.ApiPolicy; +import org.onap.dmaap.dbcapi.aaf.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 boolean usePE; + 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(); + usePE = "true".equalsIgnoreCase(p.getProperty("UsePE", "false")); + apiNamespace = p.getProperty("ApiNamespace", "org.openecomp.dmaapBC.api"); + } + apiPolicy = new ApiPolicy(); + logger.info( "usePE=" + usePE + " 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 { + 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 ( ! usePE ) 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; + } +} 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 new file mode 100644 index 0000000..e80b531 --- /dev/null +++ b/src/main/java/org/onap/dmaap/dbcapi/service/DR_NodeService.java @@ -0,0 +1,249 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dcae + * ================================================================================ + * Copyright (C) 2017 AT&T 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.service; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import javax.ws.rs.core.Response.Status; + +import org.apache.log4j.Logger; +import org.onap.dmaap.dbcapi.aaf.client.DrProvConnection; +import org.onap.dmaap.dbcapi.aaf.database.DatabaseClass; +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.model.DmaapObject.DmaapObject_Status; + +public class DR_NodeService extends BaseLoggingClass { + private class DrProv { + String currentNodes; + String currentStaticNodes; + + private String getX( String X, ApiError apiError ) { + + DrProvConnection prov = new DrProvConnection(); + prov.makeNodesConnection( X ); + String resp = prov.doGetNodes( apiError ); + logger.info( "rc=" + apiError.getCode() ); + return resp; + } + + private void setX( String X, String list, ApiError apiError ) { + DrProvConnection prov = new DrProvConnection(); + prov.makeNodesConnection( X, list ); + String resp = prov.doPutNodes( apiError ); + } + + private String removeFromList( String aNode, String aList ) { + String[] nodeList = aList.split("\\|"); + StringBuilder res = new StringBuilder(); + for ( String n: nodeList ) { + logger.info( "compare existing node " + n + " vs " + aNode ); + if ( ! n.equals(aNode)) { + if (res.length() > 0 ) { + res.append( "|" ); + } + res.append(n); + } + } + logger.info( "result=" + res.toString() ); + return res.toString(); + } + + boolean containsNode( String aNode , ApiError apiError ){ + + //DrProvConnection prov = new DrProvConnection(); + //prov.makeNodesConnection(); + currentNodes = getX( "NODES", apiError ); + if ( ! apiError.is2xx() || currentNodes == null ) { + return false; + } + logger.info( "NODES now=" + currentNodes ); + String[] nodeList = currentNodes.split("\\|"); + for( String n: nodeList ) { + logger.info( "compare existing node " + n + " vs " + aNode ); + if ( n.equals(aNode) ) { + return true; + } + } + return false; + } + + void addNode( String aNode, ApiError apiError ) { + + currentNodes = currentNodes + "|" + aNode; + setX( "NODES", currentNodes, apiError ); + + + } + void removeNode( String aNode, ApiError apiError ) { + currentNodes = removeFromList( aNode, currentNodes ); + setX( "NODES", currentNodes, apiError ); + } + + public boolean containsStaticNode(String aNode, ApiError apiError) { + + //DrProvConnection prov = new DrProvConnection(); + //prov.makeNodesConnection(); + currentStaticNodes = getX( "STATIC_ROUTING_NODES", apiError ); + if (! apiError.is2xx() || currentStaticNodes == null ) { + return false; + } + logger.info( "STATIC_ROUTING_NODES now=" + currentNodes ); + String[] nodeList = currentStaticNodes.split("\\|"); + for( String n: nodeList ) { + logger.info( "compare existing node " + n + " vs " + aNode ); + if ( n.equals(aNode) ) { + return true; + } + } + return false; + } + + + public void addStaticNode(String aNode, ApiError apiError) { + currentStaticNodes = currentStaticNodes + "|" + aNode; + setX( "STATIC_ROUTING_NODES", currentStaticNodes, apiError ); + } + void removeStaticNode( String aNode, ApiError apiError ) { + currentStaticNodes = removeFromList( aNode, currentStaticNodes ); + setX( "STATIC_ROUTING_NODES", currentStaticNodes, apiError ); + } + } + private Map<String, DR_Node> dr_nodes = DatabaseClass.getDr_nodes(); + + public Map<String, DR_Node> getDr_Nodes() { + return dr_nodes; + } + + public List<DR_Node> getAllDr_Nodes() { + return new ArrayList<DR_Node>(dr_nodes.values()); + } + + public DR_Node getDr_Node( String fqdn, ApiError apiError ) { + DR_Node old = dr_nodes.get( fqdn ); + if ( old == null ) { + apiError.setCode(Status.NOT_FOUND.getStatusCode()); + apiError.setFields( "fqdn"); + apiError.setMessage( "Node " + fqdn + " does not exist"); + return null; + } + apiError.setCode(200); + return old; + } + + public DR_Node addDr_Node( DR_Node node, ApiError apiError ) { + String fqdn = node.getFqdn(); + DR_Node old = dr_nodes.get( fqdn ); + if ( old != null ) { + apiError.setCode(Status.CONFLICT.getStatusCode()); + apiError.setFields( "fqdn"); + apiError.setMessage( "Node " + fqdn + " already exists"); + return null; + } + + DrProv drProv = new DrProv(); + + if ( ! drProv.containsNode( node.getFqdn(), apiError ) && apiError.is2xx() ) { + drProv.addNode( node.getFqdn(), apiError ); + } + if ( ! apiError.is2xx()) { + return null; + } + DcaeLocationService locService = new DcaeLocationService(); + if ( locService.isEdgeLocation( node.getDcaeLocationName()) && ! drProv.containsStaticNode( node.getFqdn(), apiError ) ) { + if ( apiError.is2xx() ) { + drProv.addStaticNode( node.getFqdn(), apiError ); + } + } + if ( ! apiError.is2xx()) { + return null; + } + + node.setLastMod(); + node.setStatus(DmaapObject_Status.VALID); + dr_nodes.put( node.getFqdn(), node ); + apiError.setCode(200); + return node; + } + + public DR_Node updateDr_Node( DR_Node node, ApiError apiError ) { + DR_Node old = dr_nodes.get( node ); + if ( old == null ) { + apiError.setCode(Status.NOT_FOUND.getStatusCode()); + apiError.setFields( "fqdn"); + apiError.setMessage( "Node " + node + " does not exist"); + return null; + } + node.setLastMod(); + dr_nodes.put( node.getFqdn(), node ); + apiError.setCode(200); + return node; + } + + public DR_Node removeDr_Node( String nodeName, ApiError apiError ) { + DR_Node old = dr_nodes.get( nodeName ); + if ( old == null ) { + apiError.setCode(Status.NOT_FOUND.getStatusCode()); + apiError.setFields( "fqdn"); + apiError.setMessage( "Node " + nodeName + " does not exist"); + return null; + } + + DrProv drProv = new DrProv(); + if ( drProv.containsNode( old.getFqdn(), apiError ) && apiError.is2xx() ) { + drProv.removeNode( old.getFqdn(), apiError ); + } + DcaeLocationService locService = new DcaeLocationService(); + if ( locService.isEdgeLocation( old.getDcaeLocationName()) && drProv.containsStaticNode( old.getFqdn(), apiError ) ) { + if ( apiError.is2xx()) { + drProv.removeStaticNode( old.getFqdn(), apiError ); + } + + } + + apiError.setCode(200); + return dr_nodes.remove(nodeName); + } + + public String getNodePatternAtLocation( String loc, boolean allowMult ) { + logger.info( "loc=" + loc ); + if ( loc == null ) { + return null; + } + StringBuilder str = new StringBuilder(); + for( DR_Node node : dr_nodes.values() ) { + if ( loc.equals( node.getDcaeLocationName()) ) { + if ( str.length() > 0 ) { + str.append( ","); + } + str.append( node.getFqdn()); + if ( ! allowMult ) { + break; + } + } + } + logger.info( "returning " + str.toString() ); + return str.toString(); + } +} 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 new file mode 100644 index 0000000..ca60b8a --- /dev/null +++ b/src/main/java/org/onap/dmaap/dbcapi/service/DR_PubService.java @@ -0,0 +1,146 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2017 AT&T 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.service; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import javax.ws.rs.core.Response.Status; + +import org.apache.log4j.Logger; +import org.onap.dmaap.dbcapi.aaf.client.DrProvConnection; +import org.onap.dmaap.dbcapi.aaf.database.DatabaseClass; +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.DR_Pub; +import org.onap.dmaap.dbcapi.model.DmaapObject.DmaapObject_Status; + +public class DR_PubService extends BaseLoggingClass{ + + private Map<String, DR_Pub> dr_pubs = DatabaseClass.getDr_pubs(); + private DR_NodeService nodeService = new DR_NodeService(); + private static DrProvConnection prov; + + public DR_PubService() { + super(); + prov = new DrProvConnection(); + } + + public Map<String, DR_Pub> getDr_Pubs() { + return dr_pubs; + } + + public List<DR_Pub> getAllDr_Pubs() { + return new ArrayList<DR_Pub>(dr_pubs.values()); + } + + public ArrayList<DR_Pub> getDr_PubsByFeedId( String feedId ) { + ArrayList<DR_Pub> somePubs = new ArrayList<DR_Pub>(); + for( DR_Pub pub : dr_pubs.values() ) { + if ( feedId.equals( pub.getFeedId() )) { + somePubs.add( pub ); + } + } + + return somePubs; + } + + public DR_Pub getDr_Pub( String key, ApiError err ) { + DR_Pub pub = dr_pubs.get( key ); + if ( pub == null ) { + err.setCode(Status.NOT_FOUND.getStatusCode()); + err.setFields( "pubId"); + err.setMessage("DR_Pub with pubId = " + key + " not found"); + } else { + err.setCode(Status.OK.getStatusCode()); + } + return pub; + } + + private void addIngressRoute( DR_Pub pub, ApiError err ) { + + String nodePattern = nodeService.getNodePatternAtLocation( pub.getDcaeLocationName(), true ); + if ( nodePattern != null && nodePattern.length() > 0 ) { + logger.info( "creating ingress rule: pub " + pub.getPubId() + " on feed " + pub.getFeedId() + " to " + nodePattern); + prov.makeIngressConnection( pub.getFeedId(), pub.getUsername(), "-", nodePattern); + int rc = prov.doXgressPost(err); + logger.info( "rc=" + rc + " error code=" + err.getCode() ); + + if ( rc != 200 ) { + switch( rc ) { + case 403: + logger.error( "Not authorized for DR ingress API"); + err.setCode(500); + err.setMessage("API deployment/configuration error - contact support"); + err.setFields( "PROV_AUTH_ADDRESSES"); + break; + + default: + logger.info( DmaapbcLogMessageEnum.INGRESS_CREATE_ERROR, Integer.toString(rc), pub.getPubId(), pub.getFeedId(), nodePattern); + } + } + + } + } + + public DR_Pub addDr_Pub( DR_Pub pub ) { + ApiError err = new ApiError(); + if ( pub.getPubId() != null && ! pub.getPubId().isEmpty() ) { + addIngressRoute( pub, err); + if ( err.getCode() > 0 ) { + pub.setStatus(DmaapObject_Status.INVALID); + } + pub.setLastMod(); + dr_pubs.put( pub.getPubId(), pub ); + return pub; + } + else { + return null; + } + } + + public DR_Pub updateDr_Pub( DR_Pub pub ) { + if ( pub.getPubId().isEmpty()) { + return null; + } + pub.setLastMod(); + dr_pubs.put( pub.getPubId(), pub ); + return pub; + } + + public DR_Pub removeDr_Pub( String pubId, ApiError err ) { + + DR_Pub pub = dr_pubs.get( pubId ); + if ( pub == null ) { + err.setCode(Status.NOT_FOUND.getStatusCode()); + err.setFields( "pubId"); + err.setMessage( "pubId " + pubId + " not found"); + } else { + dr_pubs.remove(pubId); + err.setCode(Status.OK.getStatusCode()); + } + return pub; + + } + +} 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 new file mode 100644 index 0000000..09bf8fd --- /dev/null +++ b/src/main/java/org/onap/dmaap/dbcapi/service/DR_SubService.java @@ -0,0 +1,173 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2017 AT&T 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.service; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import javax.ws.rs.core.Response.Status; + +import org.onap.dmaap.dbcapi.aaf.client.DrProvConnection; +import org.onap.dmaap.dbcapi.aaf.database.DatabaseClass; +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.DR_Sub; + +public class DR_SubService extends BaseLoggingClass { + + private Map<String, DR_Sub> dr_subs = DatabaseClass.getDr_subs(); + private DR_NodeService nodeService = new DR_NodeService(); + private String provURL; + private static DrProvConnection prov; + + + public DR_SubService( ) { + logger.debug( "Entry: DR_SubService (with no args)" ); + + } + public DR_SubService( String subURL ) { + logger.debug( "Entry: DR_SubService " + subURL ); + provURL = subURL; + } + public Map<String, DR_Sub> getDR_Subs() { + logger.debug( "enter getDR_Subs()"); + return dr_subs; + } + + public List<DR_Sub> getAllDr_Subs() { + logger.debug( "enter getAllDR_Subs()"); + return new ArrayList<DR_Sub>(dr_subs.values()); + } + + public ArrayList<DR_Sub> getDr_SubsByFeedId( String pubId ) { + ArrayList<DR_Sub> someSubs = new ArrayList<DR_Sub>(); + for( DR_Sub sub : dr_subs.values() ) { + if ( pubId.equals( sub.getFeedId() )) { + someSubs.add( sub ); + } + } + + return someSubs; + } + public DR_Sub getDr_Sub( String key, ApiError apiError ) { + logger.debug( "enter getDR_Sub()"); + DR_Sub sub = dr_subs.get( key ); + if ( sub == null ) { + apiError.setCode(Status.NOT_FOUND.getStatusCode()); + apiError.setFields( "subId"); + apiError.setMessage("subId " + key + " not found"); + } else { + apiError.setCode(200); + } + return sub; + } + + public DR_Sub addDr_Sub( DR_Sub sub, ApiError apiError ) { + logger.debug( "enter addDR_Subs()"); + prov = new DrProvConnection(); + prov.makeSubPostConnection( provURL ); + String resp = prov.doPostDr_Sub( sub, apiError ); + logger.debug( "resp=" + resp ); + + DR_Sub snew = null; + + if ( resp != null ) { + snew = new DR_Sub( resp ); + snew.setDcaeLocationName(sub.getDcaeLocationName()); + snew.setLastMod(); + addEgressRoute( snew, apiError ); + dr_subs.put( snew.getSubId(), snew ); + apiError.setCode(200); + } else { + apiError.setCode(400); + } + + return snew; + } + + private void addEgressRoute( DR_Sub sub, ApiError err ) { + + String nodePattern = nodeService.getNodePatternAtLocation( sub.getDcaeLocationName(), false ); + if ( nodePattern != null && nodePattern.length() > 0 ) { + logger.info( "creating egress rule: sub " + sub.getSubId() + " on feed " + sub.getFeedId() + " to " + nodePattern); + prov.makeEgressConnection( sub.getSubId(), nodePattern); + int rc = prov.doXgressPost(err); + logger.info( "rc=" + rc + " error code=" + err.getCode() ); + + if ( rc != 200 ) { + switch( rc ) { + case 403: + logger.error( "Not authorized for DR egress API"); + err.setCode(500); + err.setMessage("API deployment/configuration error - contact support"); + err.setFields( "PROV_AUTH_ADDRESSES"); + break; + + default: + logger.info( DmaapbcLogMessageEnum.EGRESS_CREATE_ERROR, Integer.toString(rc), sub.getSubId(), sub.getFeedId(), nodePattern); + } + } + + } + } + + public DR_Sub updateDr_Sub( DR_Sub obj, ApiError apiError ) { + logger.debug( "enter updateDR_Subs()"); + + DrProvConnection prov = new DrProvConnection(); + prov.makeSubPutConnection( obj.getSubId() ); + String resp = prov.doPutDr_Sub( obj, apiError ); + logger.debug( "resp=" + resp ); + + DR_Sub snew = null; + + if ( resp != null ) { + snew = new DR_Sub( resp ); + snew.setDcaeLocationName(obj.getDcaeLocationName()); + snew.setLastMod(); + dr_subs.put( snew.getSubId(), snew ); + apiError.setCode(200); + } else if ( apiError.is2xx()) { + apiError.setCode(400); + apiError.setMessage("unexpected empty response from DR Prov"); + } + + return snew; + } + + public void removeDr_Sub( String key, ApiError apiError ) { + logger.debug( "enter removeDR_Subs()"); + DR_Sub sub = dr_subs.get( key ); + if ( sub == null ) { + apiError.setCode(Status.NOT_FOUND.getStatusCode()); + apiError.setFields( "subId"); + apiError.setMessage("subId " + key + " not found"); + } else { + dr_subs.remove(key); + apiError.setCode(200); + } + + return; + } + +} diff --git a/src/main/java/org/onap/dmaap/dbcapi/service/DcaeLocationService.java b/src/main/java/org/onap/dmaap/dbcapi/service/DcaeLocationService.java new file mode 100644 index 0000000..44166b8 --- /dev/null +++ b/src/main/java/org/onap/dmaap/dbcapi/service/DcaeLocationService.java @@ -0,0 +1,97 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2017 AT&T 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.service; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + + + + + + + + + + + +import org.onap.dmaap.dbcapi.aaf.database.DatabaseClass; +import org.onap.dmaap.dbcapi.model.DcaeLocation; +import org.onap.dmaap.dbcapi.model.DmaapObject.DmaapObject_Status; + +public class DcaeLocationService { + + private Map<String, DcaeLocation> dcaeLocations = DatabaseClass.getDcaeLocations(); + + public Map<String, DcaeLocation> getDcaeLocations() { + return dcaeLocations; + } + + public List<DcaeLocation> getAllDcaeLocations() { + return new ArrayList<DcaeLocation>(dcaeLocations.values()); + } + + public DcaeLocation getDcaeLocation( String name ) { + return dcaeLocations.get(name); + } + + public DcaeLocation addDcaeLocation( DcaeLocation location ) { + location.setLastMod(); + location.setStatus(DmaapObject_Status.VALID); + dcaeLocations.put( location.getDcaeLocationName(), location ); + return location; + } + + public DcaeLocation updateDcaeLocation( DcaeLocation location ) { + if ( location.getDcaeLocationName().isEmpty()) { + return null; + } + location.setLastMod(); + dcaeLocations.put( location.getDcaeLocationName(), location ); + return location; + } + + public DcaeLocation removeDcaeLocation( String locationName ) { + return dcaeLocations.remove(locationName); + } + + public String getCentralLocation() { + for( Map.Entry<String, DcaeLocation> entry: dcaeLocations.entrySet() ) { + DcaeLocation loc = entry.getValue(); + if ( loc.isCentral() ) { + // use the name of the first central location we hit + return loc.getDcaeLocationName(); + } + + } + return "aCentralLocation"; // default value that is obvious to see is wrong + } + + public boolean isEdgeLocation(String aName) { + DcaeLocation loc = dcaeLocations.get(aName); + if ( ! loc.isCentral() ) { + return true; + } + return false; + } + +} diff --git a/src/main/java/org/onap/dmaap/dbcapi/service/DmaapService.java b/src/main/java/org/onap/dmaap/dbcapi/service/DmaapService.java new file mode 100644 index 0000000..8436820 --- /dev/null +++ b/src/main/java/org/onap/dmaap/dbcapi/service/DmaapService.java @@ -0,0 +1,264 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2017 AT&T 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.service; + +import java.util.ArrayList; + + + + + + + + + + +import org.onap.dmaap.dbcapi.aaf.AafService; +import org.onap.dmaap.dbcapi.aaf.DmaapGrant; +import org.onap.dmaap.dbcapi.aaf.DmaapPerm; +import org.onap.dmaap.dbcapi.aaf.AafService.ServiceType; +import org.onap.dmaap.dbcapi.aaf.authentication.ApiPerms; +import org.onap.dmaap.dbcapi.aaf.database.DatabaseClass; +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.Dmaap; +import org.onap.dmaap.dbcapi.model.MR_Client; +import org.onap.dmaap.dbcapi.model.Topic; +import org.onap.dmaap.dbcapi.model.DmaapObject.DmaapObject_Status; +import org.onap.dmaap.dbcapi.util.DmaapConfig; +import org.onap.dmaap.dbcapi.util.Singleton; + +public class DmaapService extends BaseLoggingClass { + + + private Singleton<Dmaap> dmaapholder = DatabaseClass.getDmaap(); + + // TODO put these in properties file + String topicFactory; // = "org.openecomp.dcae.dmaap.topicFactory"; + String topicMgrRole; // = "org.openecomp.dmaapBC.TopicMgr"; + + // TODO confirm this is equivalent to dmaap.getTopicNsRoot() so we can retire it + String dcaeTopicNs; // = "org.openecomp.dcae.dmaap"; + + + public DmaapService() { + DmaapConfig p = (DmaapConfig)DmaapConfig.getConfig(); + topicFactory = p.getProperty("MR.TopicFactoryNS", "MR.topicFactoryNS.not.set"); + topicMgrRole = p.getProperty("MR.TopicMgrRole", "MR.TopicMgrRole.not.set" ); + dcaeTopicNs = dmaapholder.get().getTopicNsRoot(); + + } + + public Dmaap getDmaap() { + logger.info( "entering getDmaap()" ); + return(dmaapholder.get()); + } + + public Dmaap addDmaap( Dmaap nd ) { + + logger.info( "entering addDmaap()" ); + Dmaap dmaap = dmaapholder.get(); + if ( dmaap.getVersion().equals( "0")) { + + nd.setLastMod(); + dmaapholder.update(nd); + + AafService aaf = new AafService( ServiceType.AAF_Admin); + ApiPerms p = new ApiPerms(); + p.setEnvMap(); + boolean anythingWrong = setTopicMgtPerms( nd, aaf ) || createMmaTopic(); + + if ( anythingWrong ) { + dmaap.setStatus(DmaapObject_Status.INVALID); + } + else { + dmaap.setStatus(DmaapObject_Status.VALID); + } + dmaap.setLastMod(); + dmaapholder.update(dmaap); + + return dmaap; + + } + else { + return dmaap; + } + } + + public Dmaap updateDmaap( Dmaap nd ) { + logger.info( "entering updateDmaap()" ); + + boolean anythingWrong = false; + + Dmaap dmaap = dmaapholder.get(); + + // some triggers for when we attempt to reprovision perms and MMA topic: + // - if the DMaaP Name changes + // - if the version is 0 (this is a handy test to force this processing by updating the DB) + // - if the object is invalid, reprocessing might fix it. + if ( ! dmaap.isStatusValid() || ! nd.getDmaapName().equals(dmaap.getDmaapName()) || dmaap.getVersion().equals( "0") ) { + nd.setLastMod(); + dmaapholder.update(nd); //need to set this so the following perms will pick up any new vals. + ApiPerms p = new ApiPerms(); + p.setEnvMap(); + AafService aaf = new AafService( ServiceType.AAF_Admin); + anythingWrong = setTopicMgtPerms( nd, aaf ) || createMmaTopic(); + } + + if ( anythingWrong ) { + nd.setStatus(DmaapObject_Status.INVALID); + } + else { + nd.setStatus(DmaapObject_Status.VALID); + } + nd.setLastMod(); + dmaapholder.update(nd); // may need to update status... + return(dmaapholder.get()); + + } + + public String getTopicPerm(){ + Dmaap dmaap = dmaapholder.get(); + return getTopicPerm( dmaap.getDmaapName() ); + } + public String getTopicPerm( String val ) { + Dmaap dmaap = dmaapholder.get(); + return dmaap.getTopicNsRoot() + "." + val + ".mr.topic"; + } + + public String getBridgeAdminFqtn(){ + Dmaap dmaap = dmaapholder.get(); + String topic = dmaap.getBridgeAdminTopic(); + + // check if this is already an fqtn (contains a dot) + // otherwise build it + if ( topic.indexOf('.') < 0 ) { + topic = dmaap.getTopicNsRoot() + "." + dmaap.getDmaapName() + "." + dmaap.getBridgeAdminTopic(); + } + return( topic ); + } + + private boolean setTopicMgtPerms( Dmaap nd, AafService aaf ){ + String[] actions = { "create", "destroy" }; + String instance = ":" + dcaeTopicNs + "." + nd.getDmaapName() + ".mr.topic:" + dcaeTopicNs + "." + nd.getDmaapName(); + + for( String action : actions ) { + + DmaapPerm perm = new DmaapPerm( topicFactory, instance, action ); + + int rc = aaf.addPerm( perm ); + if ( rc != 201 && rc != 409 ) { + logger.error( "unable to add perm for "+ topicFactory + "|" + instance + "|" + action ); + return true; + } + + DmaapGrant grant = new DmaapGrant( perm, topicMgrRole ); + rc = aaf.addGrant( grant ); + if ( rc != 201 && rc != 409 ) { + logger.error( "unable to grant to " + topicMgrRole + " perm for "+ topicFactory + "|" + instance + "|" + action ); + return true; + } + } + + String t = dcaeTopicNs +"." + nd.getDmaapName() + ".mr.topic"; + String[] s = { "view", "pub", "sub" }; + actions = s; + instance = "*"; + + for( String action : actions ) { + + DmaapPerm perm = new DmaapPerm( t, instance, action ); + + int rc = aaf.addPerm( perm ); + if ( rc != 201 && rc != 409 ) { + errorLogger.error( DmaapbcLogMessageEnum.AAF_UNEXPECTED_RESPONSE, Integer.toString(rc), "add perm", t + "|" + instance + "|" + action ); + return true; + } + + DmaapGrant grant = new DmaapGrant( perm, topicMgrRole ); + rc = aaf.addGrant( grant ); + if ( rc != 201 && rc != 409 ) { + errorLogger.error( DmaapbcLogMessageEnum.AAF_UNEXPECTED_RESPONSE, Integer.toString(rc), "grant to " + topicMgrRole + " perm ", topicFactory + "|" + instance + "|" + action ); + return true; + } + + } + return false; + } + + // create the special topic for MMA provisioning. + // return true indicating a problem in topic creation, + // else false means it was ok (created or previously existed) + private boolean createMmaTopic() { + boolean rc = true; + DmaapConfig p = (DmaapConfig)DmaapConfig.getConfig(); + Dmaap dmaap = dmaapholder.get(); + + ArrayList<MR_Client> clients = new ArrayList<MR_Client>(); + String[] actions = { "pub", "sub", "view" }; + String centralMR = new DcaeLocationService().getCentralLocation(); + if ( centralMR == null ) { + return rc; + } + logger.info( "Location for " + dmaap.getBridgeAdminTopic() + " is " + centralMR ); + + // first client is the Role used by Bus Controller to send messages to MMA + String provRole = p.getProperty("MM.ProvRole"); + MR_Client nClient = new MR_Client(); + nClient.setAction(actions); + nClient.setClientRole(provRole); + nClient.setDcaeLocationName(centralMR); + clients.add( nClient ); + + // second client is the Role used by MMA to listen to messages from Bus Controller + String agentRole = p.getProperty("MM.AgentRole"); + nClient = new MR_Client(); + nClient.setAction(actions); + nClient.setClientRole(agentRole); + nClient.setDcaeLocationName(centralMR); + clients.add( nClient ); + + // initialize Topic + Topic mmaTopic = new Topic(); + mmaTopic.setTopicName(dmaap.getBridgeAdminTopic()); + mmaTopic.setClients(clients); + mmaTopic.setOwner("BusController"); + mmaTopic.setTopicDescription("topic reserved for MirrorMaker Administration"); + mmaTopic.setTnxEnabled("false"); + + ApiError err = new ApiError(); + TopicService svc = new TopicService(); + try { + @SuppressWarnings("unused") + Topic nTopic = svc.addTopic(mmaTopic, err); + if ( err.is2xx() || err.getCode() == 409 ) { + return false; + } + } catch ( Exception e) { + errorLogger.error( DmaapbcLogMessageEnum.UNEXPECTED_CONDITION, " while adding Topic: " + e.getMessage()); + } + errorLogger.error( DmaapbcLogMessageEnum.TOPIC_CREATE_ERROR, dmaap.getBridgeAdminTopic(), err.getFields(), err.getFields(), err.getMessage()); + + return rc; + + } +} diff --git a/src/main/java/org/onap/dmaap/dbcapi/service/FeedService.java b/src/main/java/org/onap/dmaap/dbcapi/service/FeedService.java new file mode 100644 index 0000000..f5ea4df --- /dev/null +++ b/src/main/java/org/onap/dmaap/dbcapi/service/FeedService.java @@ -0,0 +1,359 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2017 AT&T 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.service; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import javax.ws.rs.core.Response.Status; + +import org.apache.log4j.Logger; +import org.onap.dmaap.dbcapi.aaf.client.DrProvConnection; +import org.onap.dmaap.dbcapi.aaf.database.DatabaseClass; +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.DR_Sub; +import org.onap.dmaap.dbcapi.model.Feed; +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 DR_PubService pubService = new DR_PubService(); + private DR_SubService subService = new DR_SubService(); + private DcaeLocationService dcaeLocations = new DcaeLocationService(); + private String deleteHandling; + + public FeedService() { + logger.info( "new FeedService"); + DmaapConfig p = (DmaapConfig)DmaapConfig.getConfig(); + deleteHandling = p.getProperty("Feed.deleteHandling", "DeleteOnDR"); + + } + + public Map<String, Feed> getFeeds() { + return feeds; + } + + private void getSubObjects( Feed f ) { + ArrayList<DR_Pub> pubs = pubService.getDr_PubsByFeedId( f.getFeedId() ); + f.setPubs(pubs); + ArrayList<DR_Sub> subs = subService.getDr_SubsByFeedId( f.getFeedId() ); + f.setSubs(subs); + } + + public List<Feed> getAllFeeds() { + ArrayList<Feed> fatFeeds = new ArrayList<Feed>(); + for( Feed f: feeds.values() ) { + getSubObjects(f); + fatFeeds.add(f); + } + return fatFeeds; + } + + + private Feed _getFeed( String key, ApiError err, boolean flag ) { + Feed f = feeds.get( key ); + if ( f != null && ( flag || f.getStatus() != DmaapObject_Status.DELETED ) ) { + getSubObjects( f ); + } else { + err.setCode(Status.NOT_FOUND.getStatusCode()); + err.setMessage("feed not found"); + err.setFields("feedId=" + key ); + return null; + } + err.setCode(200); + return f; + } + public Feed getFeed( String key, ApiError err ) { + return _getFeed( key, err, false ); + } + public Feed getFeedPure( String key, ApiError err ) { + return _getFeed( key, err, true ); + } + + public Feed getFeedByName( String name, String ver, ApiError err ) { + for( Feed f: feeds.values() ) { + if ( f.getFeedName().equals( name ) && f.getFeedVersion().equals(ver) ) { + getSubObjects(f); + return f; + } + + } + err.setCode(Status.NOT_FOUND.getStatusCode()); + err.setMessage("feed not found"); + err.setFields("feedName=" + name + " and ver=" + ver ); + return null; + + } + + private boolean savePubs( Feed f ) { + return savePubs( f, f ); + } + // need to save the Pub objects independently and copy pubId from original request + private boolean savePubs( Feed fnew, Feed req ) { + // save any pubs + DR_PubService pubSvc = new DR_PubService(); + ArrayList<DR_Pub> reqPubs = req.getPubs(); + ArrayList<DR_Pub> newPubs = fnew.getPubs(); + + + + int nSize = newPubs.size(); + int rSize = reqPubs.size(); + logger.info( "reqPubs size=" + rSize + " newPubs size=" + nSize ); + if ( nSize != rSize ) { + errorLogger.error( "Resulting set of publishers do not match requested set of publishers " + nSize + " vs " + rSize ); + fnew.setStatus( DmaapObject_Status.INVALID); + return false; + } + // NOTE: when i > 1 newPubs are in reverse order from reqPubs + for( int i = 0; i < reqPubs.size(); i++ ) { + DR_Pub reqPub = reqPubs.get(i); + ApiError err = new ApiError(); + if ( pubSvc.getDr_Pub( reqPub.getPubId(), err ) == null ) { + DR_Pub newPub = newPubs.get(nSize - i - 1); + reqPub.setPubId(newPub.getPubId()); + reqPub.setFeedId(newPub.getFeedId()); + reqPub.setStatus(DmaapObject_Status.VALID); + if ( reqPub.getDcaeLocationName() == null ) { + reqPub.setDcaeLocationName("notSpecified"); + } + pubSvc.addDr_Pub( reqPub ); + } + + } + + fnew.setPubs(reqPubs); + fnew.setStatus(DmaapObject_Status.VALID); + return true; + + } + + private boolean saveSubs( Feed f ) { + return saveSubs( f, f ); + } + // need to save the Sub objects independently + private boolean saveSubs( Feed fnew, Feed req ) { + ArrayList<DR_Sub> subs = req.getSubs(); + if ( subs.size() == 0 ) { + logger.info( "No subs specified"); + } else { + DR_SubService subSvc = new DR_SubService( fnew.getSubscribeURL() ); + ApiError err = new ApiError(); + for( int i = 0; i < subs.size(); i++ ) { + DR_Sub sub = subs.get(i); + if ( subSvc.getDr_Sub( sub.getSubId(), err) == null ) { + subs.set( i, subSvc.addDr_Sub(sub, err)); + if ( ! err.is2xx()) { + logger.error( "i=" + i + " url=" + sub.getDeliveryURL() + " err=" + err.getCode() ); + return false; + } + } + + } + fnew.setSubs(subs); + } + + + fnew.setStatus(DmaapObject_Status.VALID); + return true; + + } + + public Feed addFeed( Feed req, ApiError err ) { + + // at least 1 pub is required by DR, so create a default pub if none is specified + if ( req.getPubs().size() == 0 ) { + logger.info( "No pubs specified - creating tmp pub"); + ArrayList<DR_Pub> pubs = new ArrayList<DR_Pub>(); + pubs.add( new DR_Pub( dcaeLocations.getCentralLocation()) + .setRandomUserName() + .setRandomPassword()); + req.setPubs(pubs); + } + + + DrProvConnection prov = new DrProvConnection(); + prov.makeFeedConnection(); + String resp = prov.doPostFeed( req, err ); + logger.info( "resp=" + resp ); + if ( resp == null ) { + switch( err.getCode() ) { + case 400: + err.setFields( "feedName=" + req.getFeedName() + " + feedVersion=" + req.getFeedVersion() ); + break; + case 403: + err.setCode(500); + err.setMessage("API deployment/configuration error - contact support"); + err.setFields( "PROV_AUTH_ADDRESSES"); + logger.error( "Prov response: 403. " + err.getMessage() + " regarding " + err.getFields() ); + break; + default: + err.setCode(500); + err.setMessage( "Unexpected response from DR backend" ); + err.setFields("response"); + } + return null; + + } + + + Feed fnew = new Feed( resp ); + logger.info( "fnew status is:" + fnew.getStatus() ); + if ( ! fnew.isStatusValid()) { + err.setCode(500); + err.setMessage( "Unexpected response from DR backend" ); + err.setFields("response"); + return null; + } + + //saveChildren( fnew, req ); + if ( ! savePubs( fnew, req ) || ! saveSubs( fnew, req ) ) { + err.setCode(Status.BAD_REQUEST.getStatusCode()); + err.setMessage("Unable to save Pub or Sub objects"); + return null; + } + fnew.setFormatUuid(req.getFormatUuid()); + fnew.setLastMod(); + feeds.put( fnew.getFeedId(), fnew ); + return fnew; + } + + public Feed updateFeed( Feed req, ApiError err ) { + + // at least 1 pub is required by DR, so create a default pub if none is specified + if ( req.getPubs().size() == 0 ) { + logger.info( "No pubs specified - creating tmp pub"); + ArrayList<DR_Pub> pubs = new ArrayList<DR_Pub>(); + pubs.add( new DR_Pub( dcaeLocations.getCentralLocation()) + .setRandomUserName() + .setRandomPassword()); + req.setPubs(pubs); + } + + DrProvConnection prov = new DrProvConnection(); + prov.makeFeedConnection( req.getFeedId() ); + String resp = prov.doPutFeed( req, err ); + logger.info( "resp=" + resp ); + if ( resp == null ) { + switch( err.getCode() ) { + case 400: + err.setFields( "feedName=" + req.getFeedName() + " + feedVersion=" + req.getFeedVersion() ); + break; + case 403: + err.setCode(500); + err.setMessage("API deployment/configuration error - contact support"); + err.setFields( "PROV_AUTH_ADDRESSES"); + break; + default: + err.setCode(500); + err.setMessage( "Unexpected response from DR backend" ); + err.setFields("response"); + } + return null; + } + + + Feed fnew = new Feed( resp ); + logger.info( "fnew status is:" + fnew.getStatus() ); + if ( ! fnew.isStatusValid()) { + err.setCode(500); + err.setMessage( "Unexpected response from DR backend" ); + err.setFields("response"); + return null; + } + + if ( ! savePubs( fnew, req ) || ! saveSubs( fnew, req ) ) { + err.setCode(Status.BAD_REQUEST.getStatusCode()); + err.setMessage("Unable to save Pub or Sub objects"); + return null; + } + fnew.setFormatUuid(req.getFormatUuid()); + fnew.setLastMod(); + feeds.put( fnew.getFeedId(), fnew ); + return fnew; + } + + + // + // DR does not actually delete a feed, so we provide two behaviors: + // 1) clean up the feed by removing all subs and pubs, mark it here as DELETED. + // then client can add it back if desired. + // 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 ) { + + // 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); + 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); + if ( ! err.is2xx()) { + return req; + } + } + + if ( deleteHandling.equalsIgnoreCase("DeleteOnDR")) { + DrProvConnection prov = new DrProvConnection(); + prov.makeFeedConnection( req.getFeedId() ); + String resp = prov.doDeleteFeed( req, err ); + logger.info( "resp=" + resp ); + if ( resp == null ) { + switch( err.getCode() ) { + case 400: + err.setFields( "feedName=" + req.getFeedName() + " + feedVersion=" + req.getFeedVersion() ); + break; + case 403: + err.setCode(500); + err.setMessage("API deployment/configuration error - contact support"); + err.setFields( "PROV_AUTH_ADDRESSES"); + break; + default: + err.setCode(500); + err.setMessage( "Unexpected response from DR backend" ); + err.setFields("response"); + } + return req; // return back the requested feed - implies it wasn't removed + } + return feeds.remove(req.getFeedId()); + } else { + req.setStatus(DmaapObject_Status.DELETED); + req.setPubs(null); + req.setSubs(null); + req.setLastMod(); + feeds.put( req.getFeedId(), req ); + return null; + } + + + } + +} diff --git a/src/main/java/org/onap/dmaap/dbcapi/service/MR_ClientService.java b/src/main/java/org/onap/dmaap/dbcapi/service/MR_ClientService.java new file mode 100644 index 0000000..68b340f --- /dev/null +++ b/src/main/java/org/onap/dmaap/dbcapi/service/MR_ClientService.java @@ -0,0 +1,289 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2017 AT&T 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.service; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import javax.ws.rs.core.Response.Status; + + + + + + + + + +import org.onap.dmaap.dbcapi.aaf.AafService; +import org.onap.dmaap.dbcapi.aaf.DmaapGrant; +import org.onap.dmaap.dbcapi.aaf.DmaapPerm; +import org.onap.dmaap.dbcapi.aaf.AafService.ServiceType; +import org.onap.dmaap.dbcapi.aaf.client.MrProvConnection; +import org.onap.dmaap.dbcapi.aaf.database.DatabaseClass; +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.model.MR_Client; +import org.onap.dmaap.dbcapi.model.MR_Cluster; +import org.onap.dmaap.dbcapi.model.Topic; +import org.onap.dmaap.dbcapi.model.DmaapObject.DmaapObject_Status; +import org.onap.dmaap.dbcapi.util.DmaapConfig; + +public class MR_ClientService extends BaseLoggingClass{ + + private int deleteLevel; + private Map<String, MR_Client> mr_clients = DatabaseClass.getMr_clients(); + private Map<String, MR_Cluster> clusters = DatabaseClass.getMr_clusters(); + private Map<String, Topic> topics = DatabaseClass.getTopics(); + private Map<String, DcaeLocation> locations = DatabaseClass.getDcaeLocations(); + private DmaapService dmaap = new DmaapService(); + + public MR_ClientService() { + DmaapConfig p = (DmaapConfig)DmaapConfig.getConfig(); + + deleteLevel = Integer.valueOf(p.getProperty("MR.ClientDeleteLevel", "0" )); + } + + public Map<String, MR_Client> getMR_Clients() { + return mr_clients; + } + + public List<MR_Client> getAllMr_Clients() { + return new ArrayList<MR_Client>(mr_clients.values()); + } + + public ArrayList<MR_Client> getAllMrClients(String fqtn) { + ArrayList<MR_Client> results = new ArrayList<MR_Client>(); + for (Map.Entry<String, MR_Client> entry : mr_clients.entrySet()) + { + MR_Client client = entry.getValue(); + if ( fqtn.equals(client.getFqtn() ) ) { + results.add( client ); + } + } + return results; + } + + public ArrayList<MR_Client> getClientsByLocation(String location) { + ArrayList<MR_Client> results = new ArrayList<MR_Client>(); + for (Map.Entry<String, MR_Client> entry : mr_clients.entrySet()) + { + MR_Client client = entry.getValue(); + if ( location.equals(client.getDcaeLocationName() ) ) { + results.add( client ); + } + } + return results; + } + + public void refreshClients( String location ) { + ApiError err = new ApiError(); + ArrayList<MR_Client> clients = getClientsByLocation( location ); + for( MR_Client client : clients ) { + Topic topic = topics.get(client.getFqtn()); + if ( topic != null ) { + addMr_Client( client, topic, err); + } + + + } + } + + public MR_Client getMr_Client( String key, ApiError apiError ) { + MR_Client c = mr_clients.get( key ); + if ( c == null ) { + apiError.setCode(Status.NOT_FOUND.getStatusCode()); + apiError.setFields( "mrClientId"); + apiError.setMessage("mrClientId " + key + " not found" ); + } else { + apiError.setCode(200); + } + return c; + } + + public MR_Client addMr_Client( MR_Client client, Topic topic, ApiError err ) { + if ( client.getDcaeLocationName().isEmpty()) { + logger.info( "Client dcaeLocation that doesn't exist or not specified" ); + return null; + } + grantClientPerms( client, err); + if ( ! client.isStatusValid()) { + return null; + } + String centralFqdn = null; + DcaeLocation candidate = locations.get(client.getDcaeLocationName()); + if ( candidate != null && candidate.isCentral() ) { + DmaapConfig p = ( DmaapConfig)DmaapConfig.getConfig(); + centralFqdn = p.getProperty("MR.CentralCname"); + } + MR_Cluster cluster = clusters.get( client.getDcaeLocationName()); + if ( cluster != null ) { + client.setTopicURL(cluster.genTopicURL(centralFqdn, client.getFqtn())); + if ( centralFqdn == null ) { + client.setStatus( addTopicToCluster( cluster, topic, err)); + if( ! err.is2xx() && err.getCode() != 409 ) { + topic.setFqtn(err.getMessage()); + return null; + } + + } else { + MR_ClusterService clusters = new MR_ClusterService(); + // in 1610, MM should only exist for edge-to-central + // we use a cname for the central target + // but still need to provision topics on all central MRs + for( MR_Cluster central: clusters.getCentralClusters() ) { + client.setStatus( addTopicToCluster( central, topic, err)); + if( ! err.is2xx() && err.getCode() != 409 ) { + topic.setFqtn(err.getMessage()); + return null; + } + } + } + + } else { + logger.info( "Client references a dcaeLocation that doesn't exist:" + client.getDcaeLocationName()); + client.setStatus( DmaapObject_Status.STAGED); + //return null; + } + + mr_clients.put( client.getMrClientId(), client ); + + err.setCode(200); + + return client; + } + + private DmaapObject_Status addTopicToCluster( MR_Cluster cluster, Topic topic, ApiError err ){ + + MrProvConnection prov = new MrProvConnection(); + logger.info( "POST topic " + topic.getFqtn() + " to cluster " + cluster.getFqdn() + " in loc " + cluster.getDcaeLocationName()); + if ( prov.makeTopicConnection(cluster)) { + String resp = prov.doPostTopic(topic, err); + logger.info( "response code: " + err.getCode() ); + if ( err.is2xx() || err.getCode() == 409 ) { + return DmaapObject_Status.VALID; + } + } + return DmaapObject_Status.INVALID; + } + + private void grantClientPerms( MR_Client client, ApiError err) { + AafService aaf = new AafService(ServiceType.AAF_TopicMgr); + + String instance = ":topic." + client.getFqtn(); + client.setStatus( DmaapObject_Status.VALID); + for( String want : client.getAction() ) { + int rc; + DmaapPerm perm = new DmaapPerm( dmaap.getTopicPerm(), instance, want ); + DmaapGrant g = new DmaapGrant( perm, client.getClientRole() ); + rc = aaf.addGrant( g ); + if ( rc != 201 && rc != 409 ) { + client.setStatus( DmaapObject_Status.INVALID); + err.setCode(rc); + err.setMessage( "Grant of " + dmaap.getTopicPerm() + "|" + instance + "|" + want + " failed for " + client.getClientRole() ); + logger.warn( err.getMessage()); + return; + } + } + } + + private void revokeClientPerms( MR_Client client, ApiError err) { + AafService aaf = new AafService(ServiceType.AAF_TopicMgr); + + String instance = ":topic." + client.getFqtn(); + client.setStatus( DmaapObject_Status.VALID); + for( String want : client.getAction() ) { + int rc; + DmaapPerm perm = new DmaapPerm( dmaap.getTopicPerm(), instance, want ); + DmaapGrant g = new DmaapGrant( perm, client.getClientRole() ); + rc = aaf.delGrant( g ); + if ( rc != 200 && rc != 404 ) { + client.setStatus( DmaapObject_Status.INVALID); + err.setCode(rc); + err.setMessage( "Revoke of " + dmaap.getTopicPerm() + "|" + instance + "|" + want + " failed for " + client.getClientRole() ); + logger.warn( err.getMessage()); + return; + } + } + } + + public MR_Client updateMr_Client( MR_Client client, ApiError apiError ) { + MR_Client c = mr_clients.get( client.getMrClientId()); + if ( c == null ) { + apiError.setCode(Status.NOT_FOUND.getStatusCode()); + apiError.setFields( "mrClientId"); + apiError.setMessage("mrClientId " + client.getMrClientId() + " not found" ); + } else { + apiError.setCode(200); + } + mr_clients.put( client.getMrClientId(), client ); + return client; + } + + public void removeMr_Client( String key, boolean updateTopicView, ApiError apiError ) { + MR_Client client = mr_clients.get( key ); + if ( client == null ) { + apiError.setCode(Status.NOT_FOUND.getStatusCode()); + apiError.setFields( "mrClientId"); + apiError.setMessage("mrClientId " + key + " not found" ); + return; + } else { + apiError.setCode(200); + } + + if ( updateTopicView == true ) { + + TopicService topics = new TopicService(); + + Topic t = topics.getTopic(client.getFqtn(), apiError ); + if ( t != null ) { + ArrayList<MR_Client> tc = t.getClients(); + for( MR_Client c: tc) { + if ( c.getMrClientId().equals(client.getMrClientId())) { + tc.remove(c); + break; + } + } + t.setClients(tc); + topics.updateTopic( t, apiError ); + } + + } + + + // remove from AAF + if ( deleteLevel >= 2 ) { + revokeClientPerms( client, apiError ); + if ( ! apiError.is2xx()) { + return; + } + } + // remove from DB + if ( deleteLevel >= 1 ) { + mr_clients.remove(key); + } + + return; + } + +} diff --git a/src/main/java/org/onap/dmaap/dbcapi/service/MR_ClusterService.java b/src/main/java/org/onap/dmaap/dbcapi/service/MR_ClusterService.java new file mode 100644 index 0000000..977288b --- /dev/null +++ b/src/main/java/org/onap/dmaap/dbcapi/service/MR_ClusterService.java @@ -0,0 +1,149 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2017 AT&T 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.service; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import javax.ws.rs.core.Response.Status; + + + + + + + +import org.onap.dmaap.dbcapi.aaf.database.DatabaseClass; +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.model.MR_Cluster; +import org.onap.dmaap.dbcapi.model.DmaapObject.DmaapObject_Status; + +public class MR_ClusterService extends BaseLoggingClass { + + private Map<String, MR_Cluster> mr_clusters = DatabaseClass.getMr_clusters(); + + public Map<String, MR_Cluster> getMR_Clusters() { + return mr_clusters; + } + + public List<MR_Cluster> getAllMr_Clusters() { + return new ArrayList<MR_Cluster>(mr_clusters.values()); + } + + public MR_Cluster getMr_Cluster( String key, ApiError apiError ) { + MR_Cluster mrc = mr_clusters.get( key ); + if ( mrc == null ) { + apiError.setCode(Status.NOT_FOUND.getStatusCode()); + apiError.setFields( "dcaeLocationName"); + apiError.setMessage( "Cluster with dcaeLocationName " + key + " not found"); + } + apiError.setCode(200); + return mrc; + } + public MR_Cluster getMr_ClusterByFQDN( String key ) { + for( MR_Cluster cluster: mr_clusters.values() ) { + if ( key.equals( cluster.getFqdn() ) ) { + return cluster; + } + } + return null; + } + + public List<MR_Cluster> getCentralClusters() { + DcaeLocationService locations = new DcaeLocationService(); + List<MR_Cluster> result = new ArrayList<MR_Cluster>(); + for( MR_Cluster c: mr_clusters.values() ) { + if ( locations.getDcaeLocation(c.getDcaeLocationName()).isCentral() ) { + result.add(c); + } + } + return result; + } + + public MR_Cluster addMr_Cluster( MR_Cluster cluster, ApiError apiError ) { + logger.info( "Entry: addMr_Cluster"); + MR_Cluster mrc = mr_clusters.get( cluster.getDcaeLocationName() ); + if ( mrc != null ) { + apiError.setCode(Status.CONFLICT.getStatusCode()); + apiError.setFields( "dcaeLocationName"); + apiError.setMessage( "Cluster with dcaeLocationName " + cluster.getDcaeLocationName() + " already exists"); + return null; + } + cluster.setLastMod(); + cluster.setStatus(DmaapObject_Status.VALID); + mr_clusters.put( cluster.getDcaeLocationName(), cluster ); + DcaeLocationService svc = new DcaeLocationService(); + DcaeLocation loc = svc.getDcaeLocation( cluster.getDcaeLocationName() ); + if ( loc != null && loc.isCentral() ) { + ApiError resp = TopicService.setBridgeClientPerms( cluster ); + if ( ! resp.is2xx() ) { + logger.error( "Unable to provision Bridge to " + cluster.getDcaeLocationName() ); + cluster.setLastMod(); + cluster.setStatus(DmaapObject_Status.INVALID); + mr_clusters.put( cluster.getDcaeLocationName(), cluster ); + } + } + apiError.setCode(200); + return cluster; + } + + public MR_Cluster updateMr_Cluster( MR_Cluster cluster, ApiError apiError ) { + MR_Cluster mrc = mr_clusters.get( cluster.getDcaeLocationName() ); + if ( mrc == null ) { + apiError.setCode(Status.NOT_FOUND.getStatusCode()); + apiError.setFields( "dcaeLocationName"); + apiError.setMessage( "Cluster with dcaeLocationName " + cluster.getDcaeLocationName() + " not found"); + return null; + } + cluster.setLastMod(); + mr_clusters.put( cluster.getDcaeLocationName(), cluster ); + DcaeLocationService svc = new DcaeLocationService(); + DcaeLocation loc = svc.getDcaeLocation( cluster.getDcaeLocationName() ); + if ( loc.isCentral() ) { + ApiError resp = TopicService.setBridgeClientPerms( cluster ); + if ( ! resp.is2xx() ) { + logger.error( "Unable to provision Bridge to " + cluster.getDcaeLocationName() ); + cluster.setLastMod(); + cluster.setStatus(DmaapObject_Status.INVALID); + mr_clusters.put( cluster.getDcaeLocationName(), cluster ); + } + } + apiError.setCode(200); + return cluster; + } + + public MR_Cluster removeMr_Cluster( String key, ApiError apiError ) { + MR_Cluster mrc = mr_clusters.get( key ); + if ( mrc == null ) { + apiError.setCode(Status.NOT_FOUND.getStatusCode()); + apiError.setFields( "dcaeLocationName"); + apiError.setMessage( "Cluster with dcaeLocationName " + key + " not found"); + return null; + } + apiError.setCode(200); + return mr_clusters.remove(key); + } + + +} diff --git a/src/main/java/org/onap/dmaap/dbcapi/service/MirrorMakerService.java b/src/main/java/org/onap/dmaap/dbcapi/service/MirrorMakerService.java new file mode 100644 index 0000000..6701328 --- /dev/null +++ b/src/main/java/org/onap/dmaap/dbcapi/service/MirrorMakerService.java @@ -0,0 +1,141 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2017 AT&T 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.service; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + + + + + + + + + +//import org.openecomp.dmaapbc.aaf.AndrewDecryptor; +import org.onap.dmaap.dbcapi.aaf.AafDecrypt; +import org.onap.dmaap.dbcapi.aaf.client.MrTopicConnection; +import org.onap.dmaap.dbcapi.aaf.database.DatabaseClass; +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.MR_Cluster; +import org.onap.dmaap.dbcapi.model.MirrorMaker; +import org.onap.dmaap.dbcapi.model.DmaapObject.DmaapObject_Status; +import org.onap.dmaap.dbcapi.util.DmaapConfig; +import org.onap.dmaap.dbcapi.util.RandomInteger; + +public class MirrorMakerService extends BaseLoggingClass { + + private Map<String, MirrorMaker> mirrors = DatabaseClass.getMirrorMakers(); + private static MrTopicConnection prov; + private static AafDecrypt decryptor; + + public MirrorMakerService() { + super(); + + decryptor = new AafDecrypt(); + } + + // will create a MM on MMagent if needed + // will update the MMagent whitelist with all topics for this MM + public MirrorMaker updateMirrorMaker( MirrorMaker mm ) { + logger.info( "updateMirrorMaker"); + DmaapConfig p = (DmaapConfig)DmaapConfig.getConfig(); + String provUser = p.getProperty("MM.ProvUserMechId"); + String provUserPwd = decryptor.decrypt(p.getProperty( "MM.ProvUserPwd", "notSet" )); + prov = new MrTopicConnection( provUser, provUserPwd ); + + String centralFqdn = p.getProperty("MR.CentralCname", "notSet"); + + 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()); + 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.updateWhiteList()); + 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; + + } + + + + mm.setLastMod(); + return mirrors.put( mm.getMmName(), mm); + } + public MirrorMaker getMirrorMaker( String part1, String part2 ) { + logger.info( "getMirrorMaker using " + part1 + " and " + part2 ); + return mirrors.get(MirrorMaker.genKey(part1, part2)); + } + public MirrorMaker getMirrorMaker( String key ) { + logger.info( "getMirrorMaker using " + key); + return mirrors.get(key); + } + + /*public MirrorMaker updateMirrorMaker( MirrorMaker mm ) { + logger.info( "updateMirrorMaker"); + return mirrors.put( mm.getMmName(), mm); + } + */ + + public void delMirrorMaker( MirrorMaker mm ) { + logger.info( "delMirrorMaker"); + mirrors.remove(mm.getMmName()); + } + + // TODO: this should probably return sequential values or get replaced by the MM client API + // but it should be sufficient for initial 1610 development + public static String genTransactionId() { + RandomInteger ri = new RandomInteger(100000); + int randomInt = ri.next(); + return Integer.toString(randomInt); + } + public List<String> getAllMirrorMakers() { + List<String> ret = new ArrayList<String>(); + for( String key: mirrors.keySet()) { + ret.add( key ); + } + + return ret; + } + +} diff --git a/src/main/java/org/onap/dmaap/dbcapi/service/TopicService.java b/src/main/java/org/onap/dmaap/dbcapi/service/TopicService.java new file mode 100644 index 0000000..244fe37 --- /dev/null +++ b/src/main/java/org/onap/dmaap/dbcapi/service/TopicService.java @@ -0,0 +1,417 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2017 AT&T 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.service; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import javax.ws.rs.core.Response.Status; + +import org.onap.dmaap.dbcapi.aaf.AafService; +import org.onap.dmaap.dbcapi.aaf.DmaapPerm; +import org.onap.dmaap.dbcapi.aaf.AafService.ServiceType; +import org.onap.dmaap.dbcapi.aaf.database.DatabaseClass; +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.Dmaap; +import org.onap.dmaap.dbcapi.model.MR_Client; +import org.onap.dmaap.dbcapi.model.MR_Cluster; +import org.onap.dmaap.dbcapi.model.MirrorMaker; +import org.onap.dmaap.dbcapi.model.ReplicationType; +import org.onap.dmaap.dbcapi.model.Topic; +import org.onap.dmaap.dbcapi.model.DmaapObject.DmaapObject_Status; +import org.onap.dmaap.dbcapi.util.DmaapConfig; +import org.onap.dmaap.dbcapi.util.Graph; + +public class TopicService extends BaseLoggingClass { + + + + // REF: https://wiki.web.att.com/pages/viewpage.action?pageId=519703122 + private static String defaultGlobalMrHost; + + private Map<String, Topic> mr_topics = DatabaseClass.getTopics(); + private Map<String, MR_Cluster> clusters = DatabaseClass.getMr_clusters(); + + private static DmaapService dmaapSvc = new DmaapService(); + private static Dmaap dmaap = new DmaapService().getDmaap(); + private MR_ClientService clientService = new MR_ClientService(); + private MirrorMakerService bridge = new MirrorMakerService(); + + public TopicService(){ + DmaapConfig p = (DmaapConfig)DmaapConfig.getConfig(); + defaultGlobalMrHost = p.getProperty("MR.globalHost", "global.host.not.set"); + } + + public Map<String, Topic> getTopics() { + return mr_topics; + } + + public List<Topic> getAllTopics() { + ArrayList<Topic> topics = new ArrayList<Topic>(mr_topics.values()); + for( Topic topic: topics ) { + topic.setClients( clientService.getAllMrClients(topic.getFqtn())); + } + return topics; + } + + + public Topic getTopic( String key, ApiError apiError ) { + logger.info( "getTopic: key=" + key); + Topic t = mr_topics.get( key ); + if ( t == null ) { + apiError.setCode(Status.NOT_FOUND.getStatusCode()); + apiError.setFields( "fqtn"); + apiError.setMessage("topic with fqtn " + key + " not found"); + return null; + } + t.setClients( clientService.getAllMrClients( key )); + apiError.setCode(Status.OK.getStatusCode()); + return t; + } + + public Topic addTopic( Topic topic, ApiError err ) { + logger.info( "Entry: addTopic"); + String nFqtn = Topic.genFqtn( topic.getTopicName() ); + if ( getTopic( nFqtn, err ) != null ) { + String t = "topic already exists: " + nFqtn; + logger.info( t ); + err.setMessage( t ); + err.setFields( "fqtn"); + err.setCode(Status.CONFLICT.getStatusCode()); + return null; + } + err.reset(); // err filled with NOT_FOUND is expected case, but don't want to litter... + logger.info( "fqtn: " + nFqtn ); + topic.setFqtn( nFqtn ); + + AafService aaf = new AafService(ServiceType.AAF_TopicMgr); + String t = dmaap.getTopicNsRoot() + "." + dmaap.getDmaapName() + ".mr.topic"; + String instance = ":topic." + topic.getFqtn(); + + String[] actions = { "pub", "sub", "view" }; + for ( String action : actions ){ + DmaapPerm perm = new DmaapPerm( t, instance, action ); + int rc = aaf.addPerm( perm ); + if ( rc != 201 && rc != 409 ) { + err.setCode(500); + err.setMessage("Unexpected response from AAF:" + rc ); + err.setFields("t="+t + " instance="+ instance + " action="+ action); + return null; + } + } + + + if ( topic.getNumClients() > 0 ) { + ArrayList<MR_Client> clients = new ArrayList<MR_Client>(topic.getClients()); + + + ArrayList<MR_Client> clients2 = new ArrayList<MR_Client>(); + for ( Iterator<MR_Client> it = clients.iterator(); it.hasNext(); ) { + MR_Client c = it.next(); + + logger.info( "c fqtn=" + c.getFqtn() + " ID=" + c.getMrClientId() + " url=" + c.getTopicURL()); + MR_Client nc = new MR_Client( c.getDcaeLocationName(), topic.getFqtn(), c.getClientRole(), c.getAction()); + nc.setFqtn(topic.getFqtn()); + logger.info( "nc fqtn=" + nc.getFqtn() + " ID=" + nc.getMrClientId() + " url=" + nc.getTopicURL()); + clients2.add( clientService.addMr_Client(nc, topic, err)); + if ( ! err.is2xx()) { + return null; + } + } + + topic.setClients(clients2); + } + if ( topic.getReplicationCase().involvesGlobal() ) { + if ( topic.getGlobalMrURL() == null ) { + topic.setGlobalMrURL(defaultGlobalMrHost); + } + } + Topic ntopic = checkForBridge( topic, err ); + if ( ntopic == null ) { + topic.setStatus( DmaapObject_Status.INVALID); + return null; + } + + mr_topics.put( nFqtn, ntopic ); + + err.setCode(Status.OK.getStatusCode()); + return ntopic; + } + + + public Topic updateTopic( Topic topic, ApiError err ) { + logger.info( "Entry: updateTopic"); + if ( topic.getFqtn().isEmpty()) { + return null; + } + Topic ntopic = checkForBridge( topic, err ); + if ( ntopic == null ) { + topic.setStatus( DmaapObject_Status.INVALID); + return null; + } + mr_topics.put( ntopic.getFqtn(), ntopic ); + err.setCode(Status.OK.getStatusCode()); + return ntopic; + } + + public Topic removeTopic( String pubId, ApiError apiError ) { + Topic topic = mr_topics.get(pubId); + if ( topic == null ) { + apiError.setCode(Status.NOT_FOUND.getStatusCode()); + apiError.setMessage("Topic " + pubId + " does not exist"); + apiError.setFields("fqtn"); + return null; + } + ArrayList<MR_Client> clients = new ArrayList<MR_Client>(clientService.getAllMrClients( pubId )); + for ( Iterator<MR_Client> it = clients.iterator(); it.hasNext(); ) { + MR_Client c = it.next(); + + + clientService.removeMr_Client(c.getMrClientId(), false, apiError); + if ( ! apiError.is2xx()) { + return null; + } + } + apiError.setCode(Status.OK.getStatusCode()); + return mr_topics.remove(pubId); + } + public static ApiError setBridgeClientPerms( MR_Cluster node ) { + DmaapConfig p = (DmaapConfig)DmaapConfig.getConfig(); + String mmProvRole = p.getProperty("MM.ProvRole"); + String mmAgentRole = p.getProperty("MM.AgentRole"); + String[] Roles = { mmProvRole, mmAgentRole }; + String[] actions = { "view", "pub", "sub" }; + Topic bridgeAdminTopic = new Topic(); + bridgeAdminTopic.setTopicName( dmaapSvc.getBridgeAdminFqtn() ); + bridgeAdminTopic.setTopicDescription( "RESERVED topic for MirroMaker Provisioning"); + bridgeAdminTopic.setOwner( "DBC" ); + ArrayList<MR_Client> clients = new ArrayList<MR_Client>(); + for( String role: Roles ) { + MR_Client client = new MR_Client(); + client.setAction(actions); + client.setClientRole(role); + client.setDcaeLocationName( node.getDcaeLocationName()); + clients.add( client ); + } + bridgeAdminTopic.setClients(clients); + + TopicService ts = new TopicService(); + ApiError err = new ApiError(); + ts.addTopic(bridgeAdminTopic, err); + + if ( err.is2xx() || err.getCode() == 409 ){ + err.setCode(200); + return err; + } + + errorLogger.error( DmaapbcLogMessageEnum.TOPIC_CREATE_ERROR, bridgeAdminTopic.getFqtn(), Integer.toString(err.getCode()), err.getFields(), err.getMessage()); + return err; + } + + + public Topic checkForBridge( Topic topic, ApiError err ) { + + if ( topic.getReplicationCase() == ReplicationType.REPLICATION_NONE ) { + topic.setStatus( DmaapObject_Status.VALID); + return topic; + } + + boolean anythingWrong = false; + String centralFqdn = new String(); + Graph graph = new Graph( topic.getClients(), true ); + + if ( graph.isHasCentral() ) { + DmaapConfig p = (DmaapConfig)DmaapConfig.getConfig(); + centralFqdn = p.getProperty("MR.CentralCname"); + logger.info( "CentralCname=" + centralFqdn ); + } else { + logger.warn( "Topic " + topic.getFqtn() + " wants to be " + topic.getReplicationCase() + " but has no cental clients"); + } + Collection<String> locations = graph.getKeys(); + for( String loc : locations ) { + logger.info( "loc=" + loc ); + MR_Cluster cluster = clusters.get(loc); + logger.info( "cluster=" + cluster ); + + + + String source = null; + String target = null; + /* + * all replication rules have 1 bridge... + */ + switch( topic.getReplicationCase() ) { + case REPLICATION_EDGE_TO_CENTRAL: + case REPLICATION_EDGE_TO_CENTRAL_TO_GLOBAL: // NOTE: this is for E2C portion only + if ( graph.isHasCentral() && graph.getCentralLoc().equals(cluster.getDcaeLocationName())) { + break; + } + source = cluster.getFqdn(); + target = centralFqdn; + break; + case REPLICATION_CENTRAL_TO_EDGE: + if ( graph.isHasCentral() && graph.getCentralLoc().equals(cluster.getDcaeLocationName())) { + continue; + } + source = centralFqdn; + target = cluster.getFqdn(); + break; + case REPLICATION_CENTRAL_TO_GLOBAL: + if ( graph.isHasCentral() && ! graph.getCentralLoc().equals(cluster.getDcaeLocationName())) { + continue; + } + source = centralFqdn; + target = topic.getGlobalMrURL(); + break; + case REPLICATION_GLOBAL_TO_CENTRAL: + case REPLICATION_GLOBAL_TO_CENTRAL_TO_EDGE: // NOTE: this is for G2C portion only + if ( graph.isHasCentral() && ! graph.getCentralLoc().equals(cluster.getDcaeLocationName())) { + continue; + } + source = topic.getGlobalMrURL(); + target = centralFqdn; + break; + default: + logger.error( "Unexpected value for ReplicationType ("+ topic.getReplicationCase() + ") for topic " + topic.getFqtn() ); + anythingWrong = true; + continue; + } + if ( source != null && target != null ) { + try { + logger.info( "Create a MM from " + source + " to " + target ); + MirrorMaker mm = bridge.getMirrorMaker( source, target); + if ( mm == null ) { + mm = new MirrorMaker(source, target); + } + mm.addTopic(topic.getFqtn()); + bridge.updateMirrorMaker(mm); + } catch ( Exception ex ) { + err.setCode(500); + err.setFields( "mirror_maker.topic"); + err.setMessage("Unexpected condition: " + ex ); + anythingWrong = true; + break; + } + } + + + /* + * some replication rules have a 2nd bridge! + */ + source = target = null; + switch( topic.getReplicationCase() ) { + case REPLICATION_EDGE_TO_CENTRAL: + case REPLICATION_CENTRAL_TO_EDGE: + case REPLICATION_CENTRAL_TO_GLOBAL: + case REPLICATION_GLOBAL_TO_CENTRAL: + continue; + case REPLICATION_EDGE_TO_CENTRAL_TO_GLOBAL: // NOTE: this is for C2G portion only + if ( graph.isHasCentral() && ! graph.getCentralLoc().equals(cluster.getDcaeLocationName())) { + continue; + } + source = centralFqdn; + target = topic.getGlobalMrURL(); + break; + + case REPLICATION_GLOBAL_TO_CENTRAL_TO_EDGE: // NOTE: this is for C2E portion only + if ( graph.isHasCentral() && graph.getCentralLoc().equals(cluster.getDcaeLocationName())) { + continue; + } + source = centralFqdn; + target = cluster.getFqdn(); + break; + default: + logger.error( "Unexpected value for ReplicationType ("+ topic.getReplicationCase() + ") for topic " + topic.getFqtn() ); + anythingWrong = true; + break; + } + if ( source != null && target != null ) { + try { + logger.info( "Create a MM from " + source + " to " + target ); + MirrorMaker mm = bridge.getMirrorMaker( source, target); + if ( mm == null ) { + mm = new MirrorMaker(source, target); + } + mm.addTopic(topic.getFqtn()); + bridge.updateMirrorMaker(mm); + } catch ( Exception ex ) { + err.setCode(500); + err.setFields( "mirror_maker.topic"); + err.setMessage("Unexpected condition: " + ex ); + anythingWrong = true; + break; + } + } + + } + if ( anythingWrong ) { + topic.setStatus( DmaapObject_Status.INVALID); + return null; + } + + topic.setStatus( DmaapObject_Status.VALID); + return topic; + } + + /* + * Prior to 1707, we only supported EDGE_TO_CENTRAL replication. + * This was determined automatically based on presence of edge publishers and central subscribers. + * The following method is a modification of that original logic, to preserve some backwards compatibility, + * i.e. to be used when no ReplicationType is specified. + */ + public ReplicationType reviewTopic( Topic topic ) { + + + if ( topic.getNumClients() > 1 ) { + Graph graph = new Graph( topic.getClients(), false ); + + String centralFqdn = new String(); + if ( graph.isHasCentral() ) { + DmaapConfig p = (DmaapConfig)DmaapConfig.getConfig(); + centralFqdn = p.getProperty("MR.CentralCname"); + } + + Collection<String> locations = graph.getKeys(); + for( String loc : locations ) { + logger.info( "loc=" + loc ); + MR_Cluster cluster = clusters.get(loc); + if ( cluster == null ) { + logger.info( "No MR cluster for location " + loc ); + continue; + } + if ( graph.isHasCentral() && ! graph.getCentralLoc().equals(cluster.getDcaeLocationName())) { + logger.info( "Detected case for EDGE_TO_CENTRAL from " + cluster.getFqdn() + " to " + centralFqdn ); + return ReplicationType.REPLICATION_EDGE_TO_CENTRAL; + + } + + } + } + + return ReplicationType.REPLICATION_NONE; + } + +} diff --git a/src/main/java/org/onap/dmaap/dbcapi/util/DmaapConfig.java b/src/main/java/org/onap/dmaap/dbcapi/util/DmaapConfig.java new file mode 100644 index 0000000..eaa6672 --- /dev/null +++ b/src/main/java/org/onap/dmaap/dbcapi/util/DmaapConfig.java @@ -0,0 +1,50 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2017 AT&T 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 java.io.*; +import java.util.*; + +public class DmaapConfig extends Properties { + /** + * + */ + private static final long serialVersionUID = 1L; + private static String configfname = System.getProperty("ConfigFile", "etc/dmaapbc.properties"); + private static Properties config = new DmaapConfig(); + public static Properties getConfig() { + return(config); + } + public static String getConfigFileName() { + return(configfname); + } + private DmaapConfig() { + try { + InputStream is = new FileInputStream(configfname); + load(is); + is.close(); + } catch (Exception e) { + System.err.println("Unable to load configuration file " + configfname); + org.apache.log4j.Logger.getLogger(getClass()).fatal("Unable to load configuration file " + configfname, e); + System.exit(1); + } + } +} diff --git a/src/main/java/org/onap/dmaap/dbcapi/util/DmaapTimestamp.java b/src/main/java/org/onap/dmaap/dbcapi/util/DmaapTimestamp.java new file mode 100644 index 0000000..f494bed --- /dev/null +++ b/src/main/java/org/onap/dmaap/dbcapi/util/DmaapTimestamp.java @@ -0,0 +1,51 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2017 AT&T 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 java.util.Calendar; +import java.util.Date; + +import javax.xml.bind.annotation.XmlRootElement; + +import org.apache.log4j.Logger; + +@XmlRootElement +public class DmaapTimestamp { + static final Logger logger = Logger.getLogger(DmaapTimestamp.class); + private static Calendar cal = Calendar.getInstance(); + private Date stamp; + + public DmaapTimestamp() { + + stamp = cal.getTime(); + logger.info("constructor: set val to " + stamp); + } + + public void mark() { + stamp = cal.getTime(); + logger.info("mark: set val to " + stamp); + } + + public Date getVal() { + return stamp; + } + +} diff --git a/src/main/java/org/onap/dmaap/dbcapi/util/Graph.java b/src/main/java/org/onap/dmaap/dbcapi/util/Graph.java new file mode 100644 index 0000000..5c57ebc --- /dev/null +++ b/src/main/java/org/onap/dmaap/dbcapi/util/Graph.java @@ -0,0 +1,111 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2017 AT&T 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 java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.onap.dmaap.dbcapi.aaf.database.DatabaseClass; +import org.onap.dmaap.dbcapi.model.DcaeLocation; +import org.onap.dmaap.dbcapi.model.MR_Client; + + +public class Graph { + private HashMap<String, String> graph; + private boolean hasCentral; + + private Map<String, DcaeLocation> locations = DatabaseClass.getDcaeLocations(); + + //TODO add to properties file + private static String centralDcaeLayerName = "central"; + + + public Graph(HashMap<String, String> graph) { + super(); + this.graph = graph; + } + + public Graph( List<MR_Client> clients, boolean strict ) { + if ( clients == null ) + return; + this.graph = new HashMap<String, String>(); + this.hasCentral = false; + for( MR_Client client: clients ) { + if ( ! strict || client.isStatusValid()) { + String loc = client.getDcaeLocationName(); + for( String action : client.getAction() ){ + DcaeLocation dcaeLoc = locations.get(loc); + if ( ! action.equals("view") && dcaeLoc != null ) { + graph.put(loc, dcaeLoc.getDcaeLayer()); + } + } + String layer = graph.get(loc); + if ( layer != null && layer.contains(centralDcaeLayerName) ) { + this.hasCentral = true; + } + + } + } + } + + public HashMap<String, String> getGraph() { + return graph; + } + + public void setGraph(HashMap<String, String> graph) { + this.graph = graph; + } + + public String put( String key, String val ) { + return graph.put(key, val); + } + + public String get( String key ) { + return graph.get(key); + } + + public Collection<String> getKeys() { + return graph.keySet(); + } + public boolean isHasCentral() { + return hasCentral; + } + public void setHasCentral(boolean hasCentral) { + this.hasCentral = hasCentral; + } + + public String getCentralLoc() { + if ( ! hasCentral ) { + return null; + } + for( String loc : graph.keySet()) { + if ( graph.get(loc).contains(centralDcaeLayerName)) { + return loc; + } + } + return null; + } + + +} diff --git a/src/main/java/org/onap/dmaap/dbcapi/util/RandomInteger.java b/src/main/java/org/onap/dmaap/dbcapi/util/RandomInteger.java new file mode 100644 index 0000000..2909419 --- /dev/null +++ b/src/main/java/org/onap/dmaap/dbcapi/util/RandomInteger.java @@ -0,0 +1,61 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2017 AT&T 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 java.util.Date; +// source: http://www.javapractices.com/topic/TopicAction.do?Id=62 +// with some modifications +import java.util.Random; + + +public final class RandomInteger { + private static Random randomGenerator; + private int range; + + public RandomInteger( int r ) { + randomGenerator = new Random(); + randomGenerator.setSeed((new Date()).getTime()); + range = r; + } + + public int next(){ + return randomGenerator.nextInt(range); + } + + /** Generate 10 random integers in the range 0..99. */ + public static final void main(String... aArgs){ + log("Generating 10 random integers in range 0..99."); + RandomInteger ri = new RandomInteger(100); + //note a single Random object is reused here + + for (int idx = 1; idx <= 10; ++idx){ + int randomInt = ri.next(); + log("Generated : " + randomInt); + } + + log("Done."); + } + + private static void log(String aMessage){ + System.out.println(aMessage); + } +} + diff --git a/src/main/java/org/onap/dmaap/dbcapi/util/RandomString.java b/src/main/java/org/onap/dmaap/dbcapi/util/RandomString.java new file mode 100644 index 0000000..b889c1c --- /dev/null +++ b/src/main/java/org/onap/dmaap/dbcapi/util/RandomString.java @@ -0,0 +1,55 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2017 AT&T 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 java.util.Random; + +// source: http://stackoverflow.com/questions/41107/how-to-generate-a-random-alpha-numeric-string + +public class RandomString { + + private static final char[] symbols; + + static { + StringBuilder tmp = new StringBuilder(); + for (char ch = '0'; ch <= '9'; ++ch) + tmp.append(ch); + for (char ch = 'a'; ch <= 'z'; ++ch) + tmp.append(ch); + symbols = tmp.toString().toCharArray(); + } + + private final Random random = new Random(); + + private final char[] buf; + + public RandomString(int length) { + if (length < 1) + throw new IllegalArgumentException("length < 1: " + length); + buf = new char[length]; + } + + public String nextString() { + for (int idx = 0; idx < buf.length; ++idx) + buf[idx] = symbols[random.nextInt(symbols.length)]; + return new String(buf); + } + } diff --git a/src/main/java/org/onap/dmaap/dbcapi/util/Singleton.java b/src/main/java/org/onap/dmaap/dbcapi/util/Singleton.java new file mode 100644 index 0000000..3ef6a3d --- /dev/null +++ b/src/main/java/org/onap/dmaap/dbcapi/util/Singleton.java @@ -0,0 +1,28 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2017 AT&T 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; + +public interface Singleton<T> { + public T get(); + public void init(T val); + public void update(T val); + public void remove(); +} |