From 4a51a8f96715ffb2a42189b93b9fa91b453b8530 Mon Sep 17 00:00:00 2001 From: sg481n Date: Thu, 3 Aug 2017 17:39:12 -0400 Subject:  [AAF-21] Initial code import MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: Ia1dd196befd061f6ba0c2be6bf4456a30ea50f97 Signed-off-by: sg481n --- client/.gitignore | 5 + client/pom.xml | 108 ++++ .../main/java/com/att/cadi/client/AAFClient.java | 199 ++++++ .../java/com/att/cadi/client/AbsBasicAuth.java | 94 +++ .../java/com/att/cadi/client/AbsTransferSS.java | 74 +++ .../src/main/java/com/att/cadi/client/Delete.java | 71 +++ .../src/main/java/com/att/cadi/client/EClient.java | 53 ++ .../main/java/com/att/cadi/client/EnvAccess.java | 168 +++++ .../src/main/java/com/att/cadi/client/Future.java | 35 ++ client/src/main/java/com/att/cadi/client/Get.java | 49 ++ .../src/main/java/com/att/cadi/client/Holder.java | 45 ++ client/src/main/java/com/att/cadi/client/Post.java | 50 ++ .../java/com/att/cadi/client/PropertyLocator.java | 144 +++++ client/src/main/java/com/att/cadi/client/Put.java | 65 ++ .../main/java/com/att/cadi/client/RawClient.java | 159 +++++ client/src/main/java/com/att/cadi/client/Rcli.java | 697 +++++++++++++++++++++ .../src/main/java/com/att/cadi/client/Result.java | 58 ++ .../main/java/com/att/cadi/client/Retryable.java | 72 +++ .../src/main/java/com/att/cadi/dme2/DEClient.java | 223 +++++++ .../main/java/com/att/cadi/dme2/DME2BasicAuth.java | 64 ++ .../main/java/com/att/cadi/dme2/DME2ClientSS.java | 65 ++ .../main/java/com/att/cadi/dme2/DME2Locator.java | 349 +++++++++++ .../java/com/att/cadi/dme2/DME2TransferSS.java | 56 ++ .../main/java/com/att/cadi/dme2/DME2x509SS.java | 68 ++ client/src/main/java/com/att/cadi/dme2/DRcli.java | 142 +++++ .../main/java/com/att/cadi/dnsloc/DNSLocator.java | 168 +++++ .../main/java/com/att/cadi/http/HBasicAuthSS.java | 77 +++ .../src/main/java/com/att/cadi/http/HClient.java | 434 +++++++++++++ client/src/main/java/com/att/cadi/http/HMangr.java | 236 +++++++ client/src/main/java/com/att/cadi/http/HRcli.java | 134 ++++ .../main/java/com/att/cadi/http/HTransferSS.java | 66 ++ .../src/main/java/com/att/cadi/http/HX509SS.java | 168 +++++ .../java/com/att/cadi/locator/DME2Locator.java | 346 ++++++++++ .../main/java/com/att/cadi/locator/DNSLocator.java | 164 +++++ .../att/cadi/locator/HClientHotPeerLocator.java | 62 ++ .../java/com/att/cadi/locator/HotPeerLocator.java | 304 +++++++++ .../java/com/att/cadi/locator/PropertyLocator.java | 282 +++++++++ .../java/com/att/cadi/routing/GreatCircle.java | 190 ++++++ .../test/java/com/client/test/BasicDME2Client.java | 62 ++ .../test/java/com/client/test/JU_DNSLocator.java | 58 ++ .../java/com/client/test/JU_PropertyLocator.java | 99 +++ client/src/test/java/com/client/test/PaulUzee.java | 146 +++++ .../src/test/java/com/client/test/TestAccess.java | 91 +++ .../test/java/com/client/test/TestDME2Client.java | 98 +++ .../java/com/client/test/TestDME2RcliClient.java | 79 +++ .../src/test/java/com/client/test/TestHClient.java | 84 +++ 46 files changed, 6461 insertions(+) create mode 100644 client/.gitignore create mode 100644 client/pom.xml create mode 100644 client/src/main/java/com/att/cadi/client/AAFClient.java create mode 100644 client/src/main/java/com/att/cadi/client/AbsBasicAuth.java create mode 100644 client/src/main/java/com/att/cadi/client/AbsTransferSS.java create mode 100644 client/src/main/java/com/att/cadi/client/Delete.java create mode 100644 client/src/main/java/com/att/cadi/client/EClient.java create mode 100644 client/src/main/java/com/att/cadi/client/EnvAccess.java create mode 100644 client/src/main/java/com/att/cadi/client/Future.java create mode 100644 client/src/main/java/com/att/cadi/client/Get.java create mode 100644 client/src/main/java/com/att/cadi/client/Holder.java create mode 100644 client/src/main/java/com/att/cadi/client/Post.java create mode 100644 client/src/main/java/com/att/cadi/client/PropertyLocator.java create mode 100644 client/src/main/java/com/att/cadi/client/Put.java create mode 100644 client/src/main/java/com/att/cadi/client/RawClient.java create mode 100644 client/src/main/java/com/att/cadi/client/Rcli.java create mode 100644 client/src/main/java/com/att/cadi/client/Result.java create mode 100644 client/src/main/java/com/att/cadi/client/Retryable.java create mode 100644 client/src/main/java/com/att/cadi/dme2/DEClient.java create mode 100644 client/src/main/java/com/att/cadi/dme2/DME2BasicAuth.java create mode 100644 client/src/main/java/com/att/cadi/dme2/DME2ClientSS.java create mode 100644 client/src/main/java/com/att/cadi/dme2/DME2Locator.java create mode 100644 client/src/main/java/com/att/cadi/dme2/DME2TransferSS.java create mode 100644 client/src/main/java/com/att/cadi/dme2/DME2x509SS.java create mode 100644 client/src/main/java/com/att/cadi/dme2/DRcli.java create mode 100644 client/src/main/java/com/att/cadi/dnsloc/DNSLocator.java create mode 100644 client/src/main/java/com/att/cadi/http/HBasicAuthSS.java create mode 100644 client/src/main/java/com/att/cadi/http/HClient.java create mode 100644 client/src/main/java/com/att/cadi/http/HMangr.java create mode 100644 client/src/main/java/com/att/cadi/http/HRcli.java create mode 100644 client/src/main/java/com/att/cadi/http/HTransferSS.java create mode 100644 client/src/main/java/com/att/cadi/http/HX509SS.java create mode 100644 client/src/main/java/com/att/cadi/locator/DME2Locator.java create mode 100644 client/src/main/java/com/att/cadi/locator/DNSLocator.java create mode 100644 client/src/main/java/com/att/cadi/locator/HClientHotPeerLocator.java create mode 100644 client/src/main/java/com/att/cadi/locator/HotPeerLocator.java create mode 100644 client/src/main/java/com/att/cadi/locator/PropertyLocator.java create mode 100644 client/src/main/java/com/att/cadi/routing/GreatCircle.java create mode 100644 client/src/test/java/com/client/test/BasicDME2Client.java create mode 100644 client/src/test/java/com/client/test/JU_DNSLocator.java create mode 100644 client/src/test/java/com/client/test/JU_PropertyLocator.java create mode 100644 client/src/test/java/com/client/test/PaulUzee.java create mode 100644 client/src/test/java/com/client/test/TestAccess.java create mode 100644 client/src/test/java/com/client/test/TestDME2Client.java create mode 100644 client/src/test/java/com/client/test/TestDME2RcliClient.java create mode 100644 client/src/test/java/com/client/test/TestHClient.java (limited to 'client') diff --git a/client/.gitignore b/client/.gitignore new file mode 100644 index 0000000..cf85207 --- /dev/null +++ b/client/.gitignore @@ -0,0 +1,5 @@ +/bin/ +/target/ +/.classpath +/.project +.settings diff --git a/client/pom.xml b/client/pom.xml new file mode 100644 index 0000000..562a92a --- /dev/null +++ b/client/pom.xml @@ -0,0 +1,108 @@ + + + + com.att.cadi + parent + 1.3.2 + .. + + + CADI Client + cadi-client + jar + https://github.com/att/AAF + CADI + 4.0.0 + + + + com.att.inno + rosetta + + + com.att.cadi + cadi-core + + + com.att.aft + dme2 + compile + + + + + + + + org.apache.maven.plugins + maven-jarsigner-plugin + + + org.apache.maven.plugins + maven-javadoc-plugin + + false + + + + attach-javadocs + + jar + + + + + + + + org.apache.maven.plugins + maven-source-plugin + 2.2.1 + + + attach-sources + + jar-no-fork + + + + + + + + org.sonatype.plugins + nexus-staging-maven-plugin + 1.6.7 + true + + ossrhdme + https://oss.sonatype.org/ + true + + + + + + diff --git a/client/src/main/java/com/att/cadi/client/AAFClient.java b/client/src/main/java/com/att/cadi/client/AAFClient.java new file mode 100644 index 0000000..843f3b1 --- /dev/null +++ b/client/src/main/java/com/att/cadi/client/AAFClient.java @@ -0,0 +1,199 @@ +/******************************************************************************* + * ============LICENSE_START==================================================== + * * org.onap.aai + * * =========================================================================== + * * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * * Copyright © 2017 Amdocs + * * =========================================================================== + * * 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==================================================== + * * + * * ECOMP is a trademark and service mark of AT&T Intellectual Property. + * * + ******************************************************************************/ +package com.att.cadi.client; + +import java.net.HttpURLConnection; +import java.util.HashMap; +import java.util.Map; + +import com.att.aft.dme2.api.DME2Manager; +import com.att.cadi.Access; +import com.att.cadi.config.Config; +import com.att.cadi.config.SecurityInfoC; +import com.att.cadi.http.HBasicAuthSS; +import com.att.cadi.http.HMangr; +import com.att.cadi.locator.DME2Locator; +import com.att.inno.env.APIException; +import com.att.rosetta.env.RosettaDF; +import com.att.rosetta.env.RosettaEnv; + +public class AAFClient { + private RosettaEnv env; + private Map,RosettaDF> map = new HashMap,RosettaDF>(); + HMangr hman; + HBasicAuthSS ss; + + public AAFClient(RosettaEnv env) throws Exception { + this.env = env; + Access access = new EnvAccess(env); + String user = access.getProperty(Config.AAF_MECHID,null); + String password = access.decrypt(access.getProperty(Config.AAF_MECHPASS,null), true); + + SecurityInfoC si = new SecurityInfoC(access); + DME2Manager dm = new DME2Manager("APIclient DME2Manager", System.getProperties()); + DME2Locator loc = new DME2Locator(access, dm, access.getProperty(Config.AAF_URL,null)); + + int TIMEOUT = Integer.parseInt(access.getProperty(Config.AAF_CONN_TIMEOUT, "30000")); + + hman = new HMangr(access, loc).readTimeout(TIMEOUT).apiVersion("2.0"); + ss = new HBasicAuthSS(user, password, si); + } + + public AAFClient(RosettaEnv env, DME2Manager dm) throws Exception { + this.env = env; + Access access = new EnvAccess(env); + String user = access.getProperty(Config.AAF_MECHID,null); + String password = access.decrypt(access.getProperty(Config.AAF_MECHPASS,null), true); + + SecurityInfoC si = new SecurityInfoC(access); + DME2Locator loc = new DME2Locator(access, dm, access.getProperty(Config.AAF_URL,null)); + + int TIMEOUT = Integer.parseInt(access.getProperty(Config.AAF_CONN_TIMEOUT, "30000")); + + hman = new HMangr(access, loc).readTimeout(TIMEOUT).apiVersion("2.0"); + ss = new HBasicAuthSS(user, password, si); + } + + @SuppressWarnings("unchecked") + private synchronized RosettaDF getDF(Class cls) throws APIException { + RosettaDF rdf; + synchronized (env) { + rdf = map.get(cls); + if(rdf==null) { + rdf = env.newDataFactory(cls); + map.put(cls, rdf); + } + } + return (RosettaDF)rdf; + } + + // Package on purpose + static class Call { + protected final static String VOID_CONTENT_TYPE="application/Void+json;version=2.0"; + + protected RosettaDF df; + protected AAFClient client; + + public Call(AAFClient ac, RosettaDF df) { + this.client = ac; + this.df = df; + } + } + + + /////////// Calls ///////////////// + /** + * Returns a Get Object... same as "get" + * + * @param cls + * @return + * @throws APIException + */ + public Get read(Class cls) throws APIException { + return new Get(this,getDF(cls)); + } + + /** + * Returns a Get Object... same as "read" + * + * @param cls + * @return + * @throws APIException + */ + public Get get(Class cls) throws APIException { + return new Get(this,getDF(cls)); + } + + /** + * Returns a Post Object... same as "create" + * + * @param cls + * @return + * @throws APIException + */ + public Post post(Class cls) throws APIException { + return new Post(this,getDF(cls)); + } + + /** + * Returns a Post Object... same as "post" + * + * @param cls + * @return + * @throws APIException + */ + public Post create(Class cls) throws APIException { + return new Post(this,getDF(cls)); + } + + /** + * Returns a Put Object... same as "update" + * + * @param cls + * @return + * @throws APIException + */ + public Put put(Class cls) throws APIException { + return new Put(this,getDF(cls)); + } + + /** + * Returns a Put Object... same as "put" + * + * @param cls + * @return + * @throws APIException + */ + public Put update(Class cls) throws APIException { + return new Put(this,getDF(cls)); + } + + /** + * Returns a Delete Object + * + * @param cls + * @return + * @throws APIException + */ + public Delete delete(Class cls) throws APIException { + return new Delete(this,getDF(cls)); + } + + /** + * Returns a Delete Object + * + * @param cls + * @return + * @throws APIException + */ + public Delete delete() throws APIException { + return new Delete(this,null); + } + + public Put put() { + return new Put(this,null); + } + + +} diff --git a/client/src/main/java/com/att/cadi/client/AbsBasicAuth.java b/client/src/main/java/com/att/cadi/client/AbsBasicAuth.java new file mode 100644 index 0000000..ef8abf4 --- /dev/null +++ b/client/src/main/java/com/att/cadi/client/AbsBasicAuth.java @@ -0,0 +1,94 @@ +/******************************************************************************* + * ============LICENSE_START==================================================== + * * org.onap.aai + * * =========================================================================== + * * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * * Copyright © 2017 Amdocs + * * =========================================================================== + * * 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==================================================== + * * + * * ECOMP is a trademark and service mark of AT&T Intellectual Property. + * * + ******************************************************************************/ +package com.att.cadi.client; + +import java.io.IOException; + +import com.att.cadi.SecuritySetter; +import com.att.cadi.Symm; +import com.att.cadi.config.SecurityInfoC; + +public abstract class AbsBasicAuth implements SecuritySetter { + protected static final String REPEAT_OFFENDER="This call is aborted because of repeated usage of invalid Passwords"; + private static final int MAX_TEMP_COUNT = 10; + private static final int MAX_SPAM_COUNT = 10000; + private static final long WAIT_TIME = 1000*60*4; + + protected final String headValue; + protected SecurityInfoC securityInfo; + protected String user; + private long lastMiss; + private int count; + + public AbsBasicAuth(String user, String pass, SecurityInfoC si) throws IOException { + this.user = user; + headValue = "Basic " + Symm.base64.encode(user + ':' + pass); + securityInfo = si; + lastMiss=0L; + count=0; + } + + /* (non-Javadoc) + * @see com.att.cadi.SecuritySetter#getID() + */ + @Override + public String getID() { + return user; + } + + public boolean isDenied() { + if(lastMiss>0 && lastMiss>System.currentTimeMillis()) { + return true; + } else { + lastMiss=0L; + return false; + } + } + + public synchronized int setLastResponse(int httpcode) { + if(httpcode == 401) { + ++count; + if(lastMiss==0L && count>MAX_TEMP_COUNT) { + lastMiss=System.currentTimeMillis()+WAIT_TIME; + } +// if(count>MAX_SPAM_COUNT) { +// System.err.printf("Your service has %d consecutive bad service logins to AAF. \nIt will now exit\n", +// count); +// System.exit(401); +// } + if(count%1000==0) { + System.err.printf("Your service has %d consecutive bad service logins to AAF. AAF Access will be disabled after %d\n", + count,MAX_SPAM_COUNT); + } + + } else { + lastMiss=0; + } + return count; + } + + public int count() { + return count; + } +} diff --git a/client/src/main/java/com/att/cadi/client/AbsTransferSS.java b/client/src/main/java/com/att/cadi/client/AbsTransferSS.java new file mode 100644 index 0000000..3056187 --- /dev/null +++ b/client/src/main/java/com/att/cadi/client/AbsTransferSS.java @@ -0,0 +1,74 @@ +/******************************************************************************* + * ============LICENSE_START==================================================== + * * org.onap.aai + * * =========================================================================== + * * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * * Copyright © 2017 Amdocs + * * =========================================================================== + * * 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==================================================== + * * + * * ECOMP is a trademark and service mark of AT&T Intellectual Property. + * * + ******************************************************************************/ +package com.att.cadi.client; + +import java.security.Principal; + +import com.att.cadi.SecuritySetter; +import com.att.cadi.config.SecurityInfoC; +import com.att.cadi.principal.BasicPrincipal; +import com.att.cadi.principal.TGuardPrincipal; +import com.att.cadi.principal.TrustPrincipal; + +public abstract class AbsTransferSS implements SecuritySetter { + protected String value; + protected SecurityInfoC securityInfo; + protected SecuritySetter defSS; + private Principal principal; + + //Format:::[:AS][,::]* + public AbsTransferSS(Principal principal, String app) { + init(principal, app); + } + + public AbsTransferSS(Principal principal, String app, SecurityInfoC si) { + init(principal,app); + securityInfo = si; + this.defSS = si.defSS; + } + + private void init(Principal principal, String app) { + this.principal=principal; + if(principal==null) { + return; + } else if(principal instanceof BasicPrincipal) { + value = principal.getName() + ':' + app + ":BasicAuth:AS"; + } else if(principal instanceof TrustPrincipal) { + TrustPrincipal tp = (TrustPrincipal)principal; + // recursive + init(tp.original(),app); + value += principal.getName() + ':' + app + ":Trust:AS" + ',' + tp.userChain(); + } else if(principal instanceof TGuardPrincipal) { + value = principal.getName() + ':' + app + ":TGUARD:AS"; + } + } + + /* (non-Javadoc) + * @see com.att.cadi.SecuritySetter#getID() + */ + @Override + public String getID() { + return principal==null?"":principal.getName(); + } +} diff --git a/client/src/main/java/com/att/cadi/client/Delete.java b/client/src/main/java/com/att/cadi/client/Delete.java new file mode 100644 index 0000000..9367d4d --- /dev/null +++ b/client/src/main/java/com/att/cadi/client/Delete.java @@ -0,0 +1,71 @@ +/******************************************************************************* + * ============LICENSE_START==================================================== + * * org.onap.aai + * * =========================================================================== + * * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * * Copyright © 2017 Amdocs + * * =========================================================================== + * * 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==================================================== + * * + * * ECOMP is a trademark and service mark of AT&T Intellectual Property. + * * + ******************************************************************************/ +package com.att.cadi.client; + +import com.att.cadi.CadiException; +import com.att.inno.env.APIException; +import com.att.rosetta.env.RosettaDF; + +public class Delete extends AAFClient.Call { + public Delete(AAFClient ac, RosettaDF df) { + super(ac,df); + } + + @SuppressWarnings("unchecked") + public Result delete(final String pathInfo, final T t) throws Exception { + if(t==null) { + return (Result)delete(pathInfo); + } + return client.hman.best(client.ss, + new Retryable>() { + @Override + public Result code(Rcli client) throws APIException, CadiException { + Future ft = client.delete(pathInfo,df,t); + if(ft.get(client.readTimeout)) { + return Result.ok(ft.code(),ft.value); + } else { + return Result.err(ft.code(),ft.body()); + } + } + }); + } + + public Result delete(final String pathInfo) throws Exception { + return client.hman.best(client.ss, + new Retryable>() { + @Override + public Result code(Rcli client) throws APIException, CadiException { + Future ft = client.delete(pathInfo,VOID_CONTENT_TYPE); + if(ft.get(client.readTimeout)) { + return Result.ok(ft.code(),ft.value); + } else { + return Result.err(ft.code(),ft.body()); + } + } + }); + } + + + +} diff --git a/client/src/main/java/com/att/cadi/client/EClient.java b/client/src/main/java/com/att/cadi/client/EClient.java new file mode 100644 index 0000000..f508029 --- /dev/null +++ b/client/src/main/java/com/att/cadi/client/EClient.java @@ -0,0 +1,53 @@ +/******************************************************************************* + * ============LICENSE_START==================================================== + * * org.onap.aai + * * =========================================================================== + * * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * * Copyright © 2017 Amdocs + * * =========================================================================== + * * 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==================================================== + * * + * * ECOMP is a trademark and service mark of AT&T Intellectual Property. + * * + ******************************************************************************/ +package com.att.cadi.client; + +import java.io.IOException; +import java.io.OutputStream; + +import javax.servlet.http.HttpServletResponse; + +import com.att.inno.env.APIException; +import com.att.inno.env.Data; +import com.att.rosetta.env.RosettaDF; + + +public interface EClient { + public void setMethod(String meth); + public void setPathInfo(String pathinfo); + public void setPayload(Transfer transfer); + public void addHeader(String tag, String value); + public void setQueryParams(String q); + public void setFragment(String f); + public void send() throws APIException; + public Future futureCreate(Class t); + public Future futureReadString(); + public Future futureRead(RosettaDF df,Data.TYPE type); + public Future future(T t); + public Future future(HttpServletResponse resp, int expected) throws APIException; + + public interface Transfer { + public void transfer(OutputStream os) throws IOException, APIException; + } +} diff --git a/client/src/main/java/com/att/cadi/client/EnvAccess.java b/client/src/main/java/com/att/cadi/client/EnvAccess.java new file mode 100644 index 0000000..f331c9a --- /dev/null +++ b/client/src/main/java/com/att/cadi/client/EnvAccess.java @@ -0,0 +1,168 @@ +/******************************************************************************* + * ============LICENSE_START==================================================== + * * org.onap.aai + * * =========================================================================== + * * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * * Copyright © 2017 Amdocs + * * =========================================================================== + * * 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==================================================== + * * + * * ECOMP is a trademark and service mark of AT&T Intellectual Property. + * * + ******************************************************************************/ +package com.att.cadi.client; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Map.Entry; +import java.util.Properties; + +import com.att.cadi.Access; +import com.att.cadi.Symm; +import com.att.inno.env.Decryptor; +import com.att.inno.env.Env; +import com.att.inno.env.impl.BasicEnv; + +public class EnvAccess implements Access { + private Env env; + + /** + * String Property tag for files/resources that may contain properties. Can be null. + * Resources of ClassLoader will be checked first, if exist. Can be null. + * @param env + * @param tag + * @param cl + * @throws IOException + */ + public EnvAccess(BasicEnv env, ClassLoader cl) throws IOException { + this.env = env; + final Symm s = Symm.obtain(this); + env.set(new Decryptor() { + private Symm symm = s; + @Override + public String decrypt(String encrypted) { + try { + return (encrypted!=null && (encrypted.startsWith(Symm.ENC))) + ? symm.depass(encrypted) + : encrypted; + } catch (IOException e) { + return ""; + } + } + } + ); + } + + + /** + * Construct with the Classloader of Env and CADI_PROP_FILES, if possible + * + * @param env + * @throws IOException + */ + public EnvAccess(BasicEnv env) throws IOException { + this(env, env.getClass().getClassLoader()); + } + + @Override + public void log(Level level, Object... elements) { + switch(level) { + case AUDIT: + env.audit().log(elements); + break; + case DEBUG: + env.debug().log(elements); + break; + case ERROR: + env.error().log(elements); + break; + case INFO: + env.info().log(elements); + break; + case INIT: + env.init().log(elements); + break; + case WARN: + env.warn().log(elements); + break; + default: + break; + } + + } + + @Override + public void log(Exception e, Object... elements) { + env.error().log(e,elements); + } + + @Override + public void printf(Level level, String fmt, Object... elements) { + if(willLog(level)) { + log(level,String.format(fmt, elements)); + } + } + + + @Override + public boolean willLog(Level level) { + switch(level) { + case AUDIT: + return env.audit().isLoggable(); + case DEBUG: + return env.debug().isLoggable(); + case ERROR: + return env.error().isLoggable(); + case INFO: + return env.info().isLoggable(); + case INIT: + return env.init().isLoggable(); + case WARN: + return env.warn().isLoggable(); + default: + return false; + } + } + + + @Override + public void setLogLevel(Level level) { + // unused + } + + @Override + public ClassLoader classLoader() { + return env.getClass().getClassLoader(); + } + + @Override + public String getProperty(String string, String def) { + return env.getProperty(string, def); + } + + @Override + public void load(InputStream is) throws IOException { + Properties props = new Properties(); + props.load(is); + for(Entry es :props.entrySet()) { + env.setProperty(es.getKey().toString(), es.getValue().toString()); + } + } + + @Override + public String decrypt(String encrypted, boolean anytext) throws IOException { + return env.decryptor().decrypt(encrypted); + } + +} diff --git a/client/src/main/java/com/att/cadi/client/Future.java b/client/src/main/java/com/att/cadi/client/Future.java new file mode 100644 index 0000000..1752907 --- /dev/null +++ b/client/src/main/java/com/att/cadi/client/Future.java @@ -0,0 +1,35 @@ +/******************************************************************************* + * ============LICENSE_START==================================================== + * * org.onap.aai + * * =========================================================================== + * * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * * Copyright © 2017 Amdocs + * * =========================================================================== + * * 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==================================================== + * * + * * ECOMP is a trademark and service mark of AT&T Intellectual Property. + * * + ******************************************************************************/ +package com.att.cadi.client; + +import com.att.cadi.CadiException; + +public abstract class Future { + public T value; + public abstract boolean get(int timeout) throws CadiException; + + public abstract int code(); + public abstract String body(); + public abstract String header(String tag); +} diff --git a/client/src/main/java/com/att/cadi/client/Get.java b/client/src/main/java/com/att/cadi/client/Get.java new file mode 100644 index 0000000..d05654d --- /dev/null +++ b/client/src/main/java/com/att/cadi/client/Get.java @@ -0,0 +1,49 @@ +/******************************************************************************* + * ============LICENSE_START==================================================== + * * org.onap.aai + * * =========================================================================== + * * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * * Copyright © 2017 Amdocs + * * =========================================================================== + * * 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==================================================== + * * + * * ECOMP is a trademark and service mark of AT&T Intellectual Property. + * * + ******************************************************************************/ +package com.att.cadi.client; + +import com.att.cadi.CadiException; +import com.att.inno.env.APIException; +import com.att.rosetta.env.RosettaDF; + +public class Get extends AAFClient.Call { + public Get(AAFClient ac, RosettaDF df) { + super(ac,df); + } + + public Result read(final String pathInfo) throws Exception { + return client.hman.best(client.ss, + new Retryable>() { + @Override + public Result code(Rcli client) throws APIException, CadiException { + Future ft = client.read(pathInfo,df); + if(ft.get(client.readTimeout)) { + return Result.ok(ft.code(),ft.value); + } else { + return Result.err(ft.code(),ft.body()); + } + } + }); + } +} diff --git a/client/src/main/java/com/att/cadi/client/Holder.java b/client/src/main/java/com/att/cadi/client/Holder.java new file mode 100644 index 0000000..93067f9 --- /dev/null +++ b/client/src/main/java/com/att/cadi/client/Holder.java @@ -0,0 +1,45 @@ +/******************************************************************************* + * ============LICENSE_START==================================================== + * * org.onap.aai + * * =========================================================================== + * * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * * Copyright © 2017 Amdocs + * * =========================================================================== + * * 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==================================================== + * * + * * ECOMP is a trademark and service mark of AT&T Intellectual Property. + * * + ******************************************************************************/ +package com.att.cadi.client; + +/** + * Use to set Variables outside of Anonymous classes. + * + * + * @param + */ +public class Holder { + private T value; + public Holder(T t) { + value = t; + } + public void set(T t) { + value = t; + } + + public T get() { + return value; + } + +} diff --git a/client/src/main/java/com/att/cadi/client/Post.java b/client/src/main/java/com/att/cadi/client/Post.java new file mode 100644 index 0000000..7cc1b8c --- /dev/null +++ b/client/src/main/java/com/att/cadi/client/Post.java @@ -0,0 +1,50 @@ +/******************************************************************************* + * ============LICENSE_START==================================================== + * * org.onap.aai + * * =========================================================================== + * * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * * Copyright © 2017 Amdocs + * * =========================================================================== + * * 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==================================================== + * * + * * ECOMP is a trademark and service mark of AT&T Intellectual Property. + * * + ******************************************************************************/ +package com.att.cadi.client; + +import com.att.cadi.CadiException; +import com.att.cadi.LocatorException; +import com.att.inno.env.APIException; +import com.att.rosetta.env.RosettaDF; + +public class Post extends AAFClient.Call { + public Post(AAFClient ac, RosettaDF df) { + super(ac,df); + } + + public Result create(final String pathInfo, final T t) throws APIException, CadiException, LocatorException { + return client.hman.best(client.ss, + new Retryable>() { + @Override + public Result code(Rcli client) throws APIException, CadiException { + Future ft = client.create(pathInfo,df,t); + if(ft.get(client.readTimeout)) { + return Result.ok(ft.code(),ft.value); + } else { + return Result.err(ft.code(),ft.body()); + } + } + }); + } +} diff --git a/client/src/main/java/com/att/cadi/client/PropertyLocator.java b/client/src/main/java/com/att/cadi/client/PropertyLocator.java new file mode 100644 index 0000000..37bc7b6 --- /dev/null +++ b/client/src/main/java/com/att/cadi/client/PropertyLocator.java @@ -0,0 +1,144 @@ +/******************************************************************************* + * ============LICENSE_START==================================================== + * * org.onap.aai + * * =========================================================================== + * * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * * Copyright © 2017 Amdocs + * * =========================================================================== + * * 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==================================================== + * * + * * ECOMP is a trademark and service mark of AT&T Intellectual Property. + * * + ******************************************************************************/ +package com.att.cadi.client; + +import java.net.URI; +import java.net.URISyntaxException; +import java.util.Random; + +import com.att.cadi.Locator; +import com.att.cadi.LocatorException; + +public class PropertyLocator implements Locator { + private final URI [] orig; + private PLItem[] current; + private int end; + private final Random random; + + /** + * comma delimited root url list + * + * @param locList + * @throws LocatorException + */ + public PropertyLocator(String locList) throws LocatorException { + if(locList==null)throw new LocatorException("No Location List given for PropertyLocator"); + String[] locarray = locList.split("\\s*,\\s*"); + orig = new URI[locarray.length]; + + random = new Random(); + + for(int i=0;i0?current[0]:null; + } + + @Override + public boolean hasItems() { + return end>0; + } + + @Override + public Item next(Item item) throws LocatorException { + int spot; + if((spot=(((PLItem)item).order+1))>=end)return null; + return current[spot]; + } + + @Override + public synchronized void invalidate(Item item) throws LocatorException { + if(--end<=0)return; + PLItem pli = (PLItem)item; + int i,order; + for(i=0;i extends AAFClient.Call { + public Put(AAFClient ac, RosettaDF df) { + super(ac,df); + } + + public Result update(final String pathInfo, final T t) throws Exception { + return client.hman.best(client.ss, + new Retryable>() { + @Override + public Result code(Rcli client) throws APIException, CadiException { + Future ft = client.update(pathInfo,df,t); + if(ft.get(client.readTimeout)) { + return Result.ok(ft.code(),ft.value); + } else { + return Result.err(ft.code(),ft.body()); + } + } + }); + } + + public Result update(final String pathInfo) throws Exception { + return client.hman.best(client.ss, + new Retryable>() { + @Override + public Result code(Rcli client) throws APIException, CadiException { + Future ft = client.update(pathInfo); + if(ft.get(client.readTimeout)) { + return Result.ok(ft.code(),ft.value); + } else { + return Result.err(ft.code(),ft.body()); + } + } + }); + } + +} diff --git a/client/src/main/java/com/att/cadi/client/RawClient.java b/client/src/main/java/com/att/cadi/client/RawClient.java new file mode 100644 index 0000000..d1a1fc2 --- /dev/null +++ b/client/src/main/java/com/att/cadi/client/RawClient.java @@ -0,0 +1,159 @@ +/******************************************************************************* + * ============LICENSE_START==================================================== + * * org.onap.aai + * * =========================================================================== + * * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * * Copyright © 2017 Amdocs + * * =========================================================================== + * * 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==================================================== + * * + * * ECOMP is a trademark and service mark of AT&T Intellectual Property. + * * + ******************************************************************************/ +package com.att.cadi.client; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.PrintStream; +import java.net.URI; + +import com.att.aft.dme2.api.DME2Client; +import com.att.cadi.Symm; +import com.att.cadi.config.Config; + +public abstract class RawClient { + protected static String aafid, aafpass, aafurl; + protected static Symm symm; + + protected static boolean init(PrintStream out) { + try { + String propfile = System.getProperty(Config.CADI_PROP_FILES); + if(propfile==null) { + propfile = "raw.props"; + } + File pfile = new File(propfile); + if(!pfile.exists()) { + if(propfile.equals("raw.props")) { + out.println("Creating 'raw.props'. Edit for proper values, then run again. Alternatively, set " + + Config.CADI_PROP_FILES+" to a cadi properties file"); + FileOutputStream fos = new FileOutputStream(pfile); + PrintStream ps = new PrintStream(fos); + try { + ps.println("# Use http://www.bing.com/maps to figure out LAT/LONG of an Address"); + ps.println("AFT_LATITUDE=38.432930"); + ps.println("AFT_LONGITUDE=-90.432480"); + ps.println("AFT_ENVIRONMENT=AFTUAT"); + ps.print(Config.AAF_URL); + ps.println("=aaf_url=https://DME2RESOLVE/service=com.att.authz.AuthorizationService/version=2.0/envContext=DEV/routeOffer=BAU_SE"); + ps.print(Config.CADI_KEYFILE); + ps.println("="); + ps.println(Config.AAF_MECHID); + ps.print("="); + ps.println(Config.AAF_MECHPASS); + ps.print("="); + } finally { + ps.close(); + } + } + } else { + FileInputStream fis = new FileInputStream(propfile); + try { + System.getProperties().load(fis); + } finally { + fis.close(); + } + + String cadiKeyFile = System.getProperty(Config.CADI_KEYFILE); + aafid = System.getProperty(Config.AAF_MECHID); + aafpass = System.getProperty(Config.AAF_MECHPASS); + aafurl = System.getProperty(Config.AAF_URL); + out.println("Contacting: " + aafurl); + + if(cadiKeyFile==null || aafid==null || aafpass==null || aafurl==null ) { + out.print(Config.CADI_KEYFILE); + out.print(", "); + out.print(Config.CADI_KEYFILE); + out.print(", "); + out.print(Config.CADI_KEYFILE); + out.print(", "); + out.print(Config.CADI_KEYFILE); + out.print(" need to be set in "); + out.println(propfile); + } else { + fis = new FileInputStream(cadiKeyFile); + try { + symm = Symm.obtain(fis); + } finally { + fis.close(); + } + } + return true; + } + } catch (Exception e) { + e.printStackTrace(out); + } + return false; + + } + + public abstract String call(final PrintStream out, final String meth, final String path) throws Exception; + + public static void main(String[] args) { + // Sonar idiocy + PrintStream out = System.out; + + try { + if(init(out)) { + if(args.length<2) { + System.out.println("Parameters: "); + } else { + RawClient client = new DME2(); + out.println(client.call(out,args[0],args[1])); + } + } + } catch (Exception e) { + e.printStackTrace(out); + } + } + + protected static class DME2 extends RawClient { + + public String call(final PrintStream out, final String meth, final String path) { + try { + DME2Client client = new DME2Client(new URI(aafurl),10000); + client.setCredentials(aafid, symm.depass(aafpass)); + client.setMethod(meth); + client.setContext(path); + + if("GET".equalsIgnoreCase(meth) || + "DELETE".equalsIgnoreCase(meth)) { + client.setPayload(""); + } else if("POST".equalsIgnoreCase(meth) || + "PUT".equalsIgnoreCase(meth)) { + int c; + StringBuilder sb = new StringBuilder(); + while((c=System.in.read()) >=0) { + sb.append((char)c); + } + client.setPayload(sb.toString()); + } + return client.sendAndWait(10000); + } catch (Exception e) { + e.printStackTrace(out); + return ""; + } + } + } +} diff --git a/client/src/main/java/com/att/cadi/client/Rcli.java b/client/src/main/java/com/att/cadi/client/Rcli.java new file mode 100644 index 0000000..f14645e --- /dev/null +++ b/client/src/main/java/com/att/cadi/client/Rcli.java @@ -0,0 +1,697 @@ +/******************************************************************************* + * ============LICENSE_START==================================================== + * * org.onap.aai + * * =========================================================================== + * * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * * Copyright © 2017 Amdocs + * * =========================================================================== + * * 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==================================================== + * * + * * ECOMP is a trademark and service mark of AT&T Intellectual Property. + * * + ******************************************************************************/ +package com.att.cadi.client; + +import java.io.IOException; +import java.io.OutputStream; +import java.net.URI; +import java.util.Enumeration; + +import javax.servlet.ServletInputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import com.att.cadi.CadiException; +import com.att.cadi.SecuritySetter; +import com.att.inno.env.APIException; +import com.att.inno.env.Data.TYPE; +import com.att.inno.env.util.Pool; +import com.att.inno.env.util.Pool.Pooled; +import com.att.rosetta.env.RosettaDF; + +public abstract class Rcli { + public static final String BLANK = ""; + public static final String CONTENT_TYPE = "Content-Type"; + public static final String ACCEPT = "Accept"; + + protected static final String POST = "POST"; + protected static final String GET = "GET"; + protected static final String PUT = "PUT"; + protected static final String DELETE = "DELETE"; + protected TYPE type; + protected String apiVersion; + protected int readTimeout = 5000; + protected int connectionTimeout = 3000; + protected URI uri; + private String queryParams, fragment; + public static Pool buffPool = new Pool(new Pool.Creator() { + @Override + public byte[] create() throws APIException { + return new byte[1024]; + } + + @Override + public void destroy(byte[] t) { + } + + @Override + public boolean isValid(byte[] t) { + return true; + } + + @Override + public void reuse(byte[] t) { + } + }); + + + public Rcli() { + super(); + } + + public abstract void setSecuritySetter(SecuritySetter ss); + public abstract SecuritySetter getSecuritySetter(); + + + public Rcli forUser(SecuritySetter ss) { + Rcli rv = clone(uri==null?this.uri:uri,ss); + setSecuritySetter(ss); + rv.type = type; + rv.apiVersion = apiVersion; + return rv; + } + + protected abstract Rcli clone(URI uri, SecuritySetter ss); + + public abstract void invalidate() throws CadiException; + + public Rcli readTimeout(int millis) { + readTimeout = millis; + return this; + } + + public Rcli connectionTimeout(int millis) { + connectionTimeout = millis; + return this; + } + + public Rcli type(TYPE type) { + this.type=type; + return this; + } + + public Rcli apiVersion(String apiVersion) { + this.apiVersion = apiVersion; + return this; + } + + public boolean isApiVersion(String prospective) { + return apiVersion.equals(prospective); + } + + + public String typeString(Class cls) { + return "application/"+cls.getSimpleName()+"+"+type.name().toLowerCase()+ + (apiVersion==null?BLANK:";version="+apiVersion); + } + + protected abstract EClient client() throws CadiException; + + + public Future create(String pathinfo, String contentType, final RosettaDF df, final T t) throws APIException, CadiException { + final int idx = pathinfo.indexOf('?'); + final String qp; + if(idx>=0) { + qp=pathinfo.substring(idx+1); + pathinfo=pathinfo.substring(0,idx); + } else { + qp=queryParams; + } + EClient client = client(); + client.setMethod(POST); + client.addHeader(CONTENT_TYPE,contentType); + client.setPathInfo(pathinfo); + client.setQueryParams(qp); + client.setFragment(fragment); + client.setPayload(new EClient.Transfer() { + @Override + public void transfer(OutputStream os) throws IOException, APIException { + df.newData().out(type).direct(t,os); + } + }); + client.send(); + queryParams = fragment = null; + return client.futureCreate(df.getTypeClass()); + } + + public Future create(String pathinfo, final RosettaDF df, final T t) throws APIException, CadiException { + final int idx = pathinfo.indexOf('?'); + final String qp; + if(idx>=0) { + qp=pathinfo.substring(idx+1); + pathinfo=pathinfo.substring(0,idx); + } else { + qp=queryParams; + } + EClient client = client(); + client.setMethod(POST); + client.addHeader(CONTENT_TYPE,typeString(df.getTypeClass())); + client.setPathInfo(pathinfo); + client.setQueryParams(qp); + client.setFragment(fragment); + client.setPayload(new EClient.Transfer() { + @Override + public void transfer(OutputStream os) throws IOException, APIException { + df.newData().out(type).direct(t,os); + } + }); + client.send(); + queryParams = fragment = null; + return client.futureCreate(df.getTypeClass()); + } + + public Future create(String pathinfo, Class cls, final RosettaDF df, final T t) throws APIException, CadiException { + final int idx = pathinfo.indexOf('?'); + final String qp; + if(idx>=0) { + qp=pathinfo.substring(idx+1); + pathinfo=pathinfo.substring(0,idx); + } else { + qp=queryParams; + } + + EClient client = client(); + client.setMethod(POST); + client.addHeader(CONTENT_TYPE,typeString(cls)); + client.setPathInfo(pathinfo); + client.setQueryParams(qp); + client.setFragment(fragment); + client.setPayload(new EClient.Transfer() { + @Override + public void transfer(OutputStream os) throws IOException, APIException { + df.newData().out(type).direct(t,os); + } + }); + client.send(); + queryParams = fragment = null; + return client.futureCreate(df.getTypeClass()); + } + + public Future create(String pathinfo, Class cls) throws APIException, CadiException { + final int idx = pathinfo.indexOf('?'); + final String qp; + if(idx>=0) { + qp=pathinfo.substring(idx+1); + pathinfo=pathinfo.substring(0,idx); + } else { + qp=queryParams; + } + + EClient client = client(); + client.setMethod(POST); + client.addHeader(CONTENT_TYPE,typeString(cls)); + client.setPathInfo(pathinfo); + client.setQueryParams(qp); + client.setFragment(fragment); + client.setPayload(null); + client.send(); + queryParams = fragment = null; + return client.futureCreate(cls); + } + + public Future create(String pathinfo, String contentType) throws APIException, CadiException { + final int idx = pathinfo.indexOf('?'); + final String qp; + if(idx>=0) { + qp=pathinfo.substring(idx+1); + pathinfo=pathinfo.substring(0,idx); + } else { + qp=queryParams; + } + + EClient client = client(); + client.setMethod(POST); + client.addHeader(CONTENT_TYPE,contentType); + client.setPathInfo(pathinfo); + client.setQueryParams(qp); + client.setFragment(fragment); + client.setPayload(null); + client.send(); + queryParams = fragment = null; + return client.futureCreate(Void.class); + } + + + public Future read(String pathinfo, String accept, String ... headers) throws APIException, CadiException { + final int idx = pathinfo.indexOf('?'); + final String qp; + if(idx>=0) { + qp=pathinfo.substring(idx+1); + pathinfo=pathinfo.substring(0,idx); + } else { + qp=queryParams; + } + + EClient client = client(); + client.setMethod(GET); + client.addHeader(ACCEPT, accept); + + for(int i=1;i Future read(String pathinfo, String accept, RosettaDF df, String ... headers) throws APIException, CadiException { + final int idx = pathinfo.indexOf('?'); + final String qp; + if(idx>=0) { + qp=pathinfo.substring(idx+1); + pathinfo=pathinfo.substring(0,idx); + } else { + qp=queryParams; + } + + EClient client = client(); + client.setMethod(GET); + client.addHeader(ACCEPT, accept); + for(int i=1;i Future read(String pathinfo, RosettaDF df,String ... headers) throws APIException, CadiException { + final int idx = pathinfo.indexOf('?'); + final String qp; + if(idx>=0) { + qp=pathinfo.substring(idx+1); + pathinfo=pathinfo.substring(0,idx); + } else { + qp=queryParams; + } + + EClient client = client(); + client.setMethod(GET); + client.addHeader(ACCEPT, typeString(df.getTypeClass())); + for(int i=1;i Future read(String pathinfo, Class cls, RosettaDF df) throws APIException, CadiException { + final int idx = pathinfo.indexOf('?'); + final String qp; + if(idx>=0) { + qp=pathinfo.substring(idx+1); + pathinfo=pathinfo.substring(0,idx); + } else { + qp=queryParams; + } + + EClient client = client(); + client.setMethod(GET); + client.addHeader(ACCEPT, typeString(cls)); + client.setQueryParams(qp); + client.setFragment(fragment); + client.setPathInfo(pathinfo); + + client.setPayload(null); + client.send(); + queryParams = fragment = null; + return client.futureRead(df,type); + } + + public Future update(String pathinfo, String contentType, final RosettaDF df, final T t) throws APIException, CadiException { + final int idx = pathinfo.indexOf('?'); + final String qp; + if(idx>=0) { + qp=pathinfo.substring(idx+1); + pathinfo=pathinfo.substring(0,idx); + } else { + qp=queryParams; + } + + EClient client = client(); + client.setMethod(PUT); + client.addHeader(CONTENT_TYPE,contentType); + client.setQueryParams(qp); + client.setFragment(fragment); + client.setPathInfo(pathinfo); + client.setPayload(new EClient.Transfer() { + @Override + public void transfer(OutputStream os) throws IOException, APIException { + df.newData().out(type).direct(t,os); + } + }); + client.send(); + queryParams = fragment = null; + return client.future(t); + } + + public Future updateRespondString(String pathinfo, final RosettaDF df, final T t) throws APIException, CadiException { + final int idx = pathinfo.indexOf('?'); + final String qp; + if(idx>=0) { + qp=pathinfo.substring(idx+1); + pathinfo=pathinfo.substring(0,idx); + } else { + qp=queryParams; + } + + EClient client = client(); + client.setMethod(PUT); + client.addHeader(CONTENT_TYPE, typeString(df.getTypeClass())); + client.setQueryParams(qp); + client.setFragment(fragment); + client.setPathInfo(pathinfo); + client.setPayload(new EClient.Transfer() { + @Override + public void transfer(OutputStream os) throws IOException, APIException { + df.newData().out(type).direct(t,os); + } + }); + client.send(); + queryParams = fragment = null; + return client.futureReadString(); + } + + + public Future update(String pathinfo, final RosettaDF df, final T t) throws APIException, CadiException { + final int idx = pathinfo.indexOf('?'); + final String qp; + if(idx>=0) { + qp=pathinfo.substring(idx+1); + pathinfo=pathinfo.substring(0,idx); + } else { + qp=queryParams; + } + + EClient client = client(); + client.setMethod(PUT); + client.addHeader(CONTENT_TYPE, typeString(df.getTypeClass())); + client.setQueryParams(qp); + client.setFragment(fragment); + client.setPathInfo(pathinfo); + client.setPayload(new EClient.Transfer() { + @Override + public void transfer(OutputStream os) throws IOException, APIException { + df.newData().out(type).direct(t,os); + } + }); + client.send(); + queryParams = fragment = null; + return client.future(t); + } + + public Future update(String pathinfo, Class cls, final RosettaDF df, final T t) throws APIException, CadiException { + final int idx = pathinfo.indexOf('?'); + final String qp; + if(idx>=0) { + qp=pathinfo.substring(idx+1); + pathinfo=pathinfo.substring(0,idx); + } else { + qp=queryParams; + } + + EClient client = client(); + client.setMethod(PUT); + client.addHeader(CONTENT_TYPE, typeString(cls)); + client.setQueryParams(qp); + client.setFragment(fragment); + client.setPathInfo(pathinfo); + client.setPayload(new EClient.Transfer() { + @Override + public void transfer(OutputStream os) throws IOException, APIException { + df.newData().out(type).direct(t,os); + } + }); + client.send(); + queryParams = fragment = null; + return client.future(t); + } + + /** + * A method to update with a VOID + * @param pathinfo + * @param resp + * @param expected + * @return + * @throws APIException + * @throws CadiException + */ + public Future update(String pathinfo) throws APIException, CadiException { + final int idx = pathinfo.indexOf('?'); + final String qp; + if(idx>=0) { + qp=pathinfo.substring(idx+1); + pathinfo=pathinfo.substring(0,idx); + } else { + qp=queryParams; + } + + EClient client = client(); + client.setMethod(PUT); + client.addHeader(CONTENT_TYPE, typeString(Void.class)); + client.setQueryParams(qp); + client.setFragment(fragment); + client.setPathInfo(pathinfo); +// client.setPayload(new EClient.Transfer() { +// @Override +// public void transfer(OutputStream os) throws IOException, APIException { +// } +// }); + client.send(); + queryParams = fragment = null; + return client.future(null); + } + + public Future delete(String pathinfo, String contentType, final RosettaDF df, final T t) throws APIException, CadiException { + final int idx = pathinfo.indexOf('?'); + final String qp; + if(idx>=0) { + qp=pathinfo.substring(idx+1); + pathinfo=pathinfo.substring(0,idx); + } else { + qp=queryParams; + } + + EClient client = client(); + client.setMethod(DELETE); + client.addHeader(CONTENT_TYPE, contentType); + client.setQueryParams(qp); + client.setFragment(fragment); + client.setPathInfo(pathinfo); + client.setPayload(new EClient.Transfer() { + @Override + public void transfer(OutputStream os) throws IOException, APIException { + df.newData().out(type).direct(t,os); + } + }); + client.send(); + queryParams = fragment = null; + return client.future(t); + } + + public Future delete(String pathinfo, Class cls, final RosettaDF df, final T t) throws APIException, CadiException { + final int idx = pathinfo.indexOf('?'); + final String qp; + if(idx>=0) { + qp=pathinfo.substring(idx+1); + pathinfo=pathinfo.substring(0,idx); + } else { + qp=queryParams; + } + + EClient client = client(); + client.setMethod(DELETE); + client.addHeader(CONTENT_TYPE, typeString(cls)); + client.setQueryParams(qp); + client.setFragment(fragment); + client.setPathInfo(pathinfo); + client.setPayload(new EClient.Transfer() { + @Override + public void transfer(OutputStream os) throws IOException, APIException { + df.newData().out(type).direct(t,os); + } + }); + client.send(); + queryParams = fragment = null; + return client.future(t); + } + + public Future delete(String pathinfo, final RosettaDF df, final T t) throws APIException, CadiException { + final int idx = pathinfo.indexOf('?'); + final String qp; + if(idx>=0) { + qp=pathinfo.substring(idx+1); + pathinfo=pathinfo.substring(0,idx); + } else { + qp=queryParams; + } + + EClient client = client(); + client.setMethod(DELETE); + client.addHeader(CONTENT_TYPE, typeString(df.getTypeClass())); + client.setQueryParams(qp); + client.setFragment(fragment); + client.setPathInfo(pathinfo); + client.setPayload(new EClient.Transfer() { + @Override + public void transfer(OutputStream os) throws IOException, APIException { + df.newData().out(type).direct(t,os); + } + }); + + client.send(); + queryParams = fragment = null; + return client.future(t); + } + + + public Future delete(String pathinfo, Class cls) throws APIException, CadiException { + final int idx = pathinfo.indexOf('?'); + final String qp; + if(idx>=0) { + qp=pathinfo.substring(idx+1); + pathinfo=pathinfo.substring(0,idx); + } else { + qp=queryParams; + } + + EClient client = client(); + client.setMethod(DELETE); + client.addHeader(CONTENT_TYPE, typeString(cls)); + client.setQueryParams(qp); + client.setFragment(fragment); + client.setPathInfo(pathinfo); + client.setPayload(null); + client.send(); + queryParams = fragment = null; + return client.future((T)null); + } + + public Future delete(String pathinfo, String contentType) throws APIException, CadiException { + final int idx = pathinfo.indexOf('?'); + final String qp; + if(idx>=0) { + qp=pathinfo.substring(idx+1); + pathinfo=pathinfo.substring(0,idx); + } else { + qp=queryParams; + } + + EClient client = client(); + client.setMethod(DELETE); + client.addHeader(CONTENT_TYPE, contentType); + client.setQueryParams(qp); + client.setFragment(fragment); + client.setPathInfo(pathinfo); + client.setPayload(null); + client.send(); + queryParams = fragment = null; + return client.future(null); + } + + public Future transfer(final HttpServletRequest req, final HttpServletResponse resp, final String pathParam, final int expected) throws CadiException, APIException { + EClient client = client(); + URI uri; + try { + uri = new URI(req.getRequestURI()); + } catch (Exception e) { + throw new CadiException("Invalid incoming URI",e); + } + String name; + for(Enumeration en = req.getHeaderNames();en.hasMoreElements();) { + name = en.nextElement(); + client.addHeader(name,req.getHeader(name)); + } + client.setQueryParams(req.getQueryString()); + client.setFragment(uri.getFragment()); + client.setPathInfo(pathParam); + String meth = req.getMethod(); + client.setMethod(meth); + if(!"GET".equals(meth)) { + client.setPayload(new EClient.Transfer() { + @Override + public void transfer(OutputStream os) throws IOException, APIException { + final ServletInputStream is = req.getInputStream(); + int read; + // reuse Buffers + Pooled pbuff = buffPool.get(); + try { + while((read=is.read(pbuff.content))>=0) { + os.write(pbuff.content,0,read); + } + } finally { + pbuff.done(); + } + } + }); + } + client.send(); + return client.future(resp, expected); + } + + public String toString() { + return uri.toString(); + } + + /** + * @param queryParams the queryParams to set + * @return + */ + public Rcli setQueryParams(String queryParams) { + this.queryParams = queryParams; + return this; + } + + + /** + * @param fragment the fragment to set + * @return + */ + public Rcli setFragment(String fragment) { + this.fragment = fragment; + return this; + } + + public URI getURI() { + return uri; + } + +} diff --git a/client/src/main/java/com/att/cadi/client/Result.java b/client/src/main/java/com/att/cadi/client/Result.java new file mode 100644 index 0000000..1e4909e --- /dev/null +++ b/client/src/main/java/com/att/cadi/client/Result.java @@ -0,0 +1,58 @@ +/******************************************************************************* + * ============LICENSE_START==================================================== + * * org.onap.aai + * * =========================================================================== + * * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * * Copyright © 2017 Amdocs + * * =========================================================================== + * * 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==================================================== + * * + * * ECOMP is a trademark and service mark of AT&T Intellectual Property. + * * + ******************************************************************************/ +package com.att.cadi.client; + +public class Result { + public final int code; + public final T value; + public final String error; + + private Result(int code, T value, String error) { + this.code = code; + this.value = value; + this.error = error; + } + + public static Result ok(int code,T t) { + return new Result(code,t,null); + } + + public static Result err(int code,String body) { + return new Result(code,null,body); + } + + public boolean isOK() { + return error==null; + } + + public String toString() { + StringBuilder sb = new StringBuilder("Code: "); + sb.append(code); + if(error!=null) { + sb.append(" = "); + sb.append(error); + } + return sb.toString(); + } +} diff --git a/client/src/main/java/com/att/cadi/client/Retryable.java b/client/src/main/java/com/att/cadi/client/Retryable.java new file mode 100644 index 0000000..e276837 --- /dev/null +++ b/client/src/main/java/com/att/cadi/client/Retryable.java @@ -0,0 +1,72 @@ +/******************************************************************************* + * ============LICENSE_START==================================================== + * * org.onap.aai + * * =========================================================================== + * * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * * Copyright © 2017 Amdocs + * * =========================================================================== + * * 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==================================================== + * * + * * ECOMP is a trademark and service mark of AT&T Intellectual Property. + * * + ******************************************************************************/ +package com.att.cadi.client; + +import java.net.ConnectException; + +import com.att.cadi.CadiException; +import com.att.cadi.Locator; +import com.att.inno.env.APIException; + +/** + * + * + * @param + * @param + */ +public abstract class Retryable { + // be able to hold state for consistent Connections. Not required for all connection types. + public Rcli lastClient; + private Locator.Item item; + + public Retryable() { + lastClient = null; + item = null; + } + + public Retryable(Retryable ret) { + lastClient = ret.lastClient; + item = ret.item; + } + + public Locator.Item item(Locator.Item item) { + lastClient = null; + this.item = item; + return item; + } + public Locator.Item item() { + return item; + } + + public abstract RET code(Rcli client) throws CadiException, ConnectException, APIException; + + /** + * Note, Retryable is tightly coupled to the Client Utilizing. It will not be the wrong type. + * @return + */ + @SuppressWarnings("unchecked") + public Rcli lastClient() { + return (Rcli)lastClient; + } +} diff --git a/client/src/main/java/com/att/cadi/dme2/DEClient.java b/client/src/main/java/com/att/cadi/dme2/DEClient.java new file mode 100644 index 0000000..6810916 --- /dev/null +++ b/client/src/main/java/com/att/cadi/dme2/DEClient.java @@ -0,0 +1,223 @@ +/******************************************************************************* + * ============LICENSE_START==================================================== + * * org.onap.aai + * * =========================================================================== + * * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * * Copyright © 2017 Amdocs + * * =========================================================================== + * * 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==================================================== + * * + * * ECOMP is a trademark and service mark of AT&T Intellectual Property. + * * + ******************************************************************************/ +package com.att.cadi.dme2; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.net.URI; + +import javax.servlet.http.HttpServletResponse; + +import com.att.aft.dme2.api.DME2Client; +import com.att.aft.dme2.api.DME2Exception; +import com.att.aft.dme2.api.DME2Manager; +import com.att.aft.dme2.handler.DME2RestfulHandler; +import com.att.aft.dme2.handler.DME2RestfulHandler.ResponseInfo; +import com.att.cadi.CadiException; +import com.att.cadi.SecuritySetter; +import com.att.cadi.client.EClient; +import com.att.cadi.client.Future; +import com.att.cadi.client.Rcli; +import com.att.inno.env.APIException; +import com.att.inno.env.Data; +import com.att.rosetta.env.RosettaDF; + +public class DEClient implements EClient { + private DME2Client client; + private DME2RestfulHandler replyHandler; + private EClient.Transfer payload; + private boolean isProxy; + private SecuritySetter ss; + + public DEClient(DME2Manager manager, SecuritySetter ss, URI uri, long timeout) throws DME2Exception, CadiException { + client = new DME2Client(manager,uri,timeout); + client.setAllowAllHttpReturnCodes(true); + this.ss = ss; + ss.setSecurity(client); + replyHandler = new DME2RestfulHandler(Rcli.BLANK); + client.setReplyHandler(replyHandler); + } + + @Override + public void setMethod(String meth) { + client.setMethod(meth); + } + + /** + * DME2 can't handle having QueryParams on the URL line, but it is the most natural way, so... + * + * Also, DME2 can't handle "/proxy" as part of Context in the main URI line, so we add it when we see authz-gw to "isProxy" + */ + public void setPathInfo(String pathinfo) { + int qp = pathinfo.indexOf('?'); + if(qp<0) { + client.setContext(isProxy?("/proxy"+pathinfo):pathinfo); + } else { + client.setContext(isProxy?("/proxy"+pathinfo.substring(0,qp)):pathinfo.substring(0,qp)); + client.setQueryParams(pathinfo.substring(qp+1)); + } + } + + @Override + public void setPayload(EClient.Transfer transfer) { + payload = transfer; + } + + @Override + public void addHeader(String tag, String value) { + client.addHeader(tag, value); + } + + + @Override + public void setQueryParams(String q) { + client.setQueryParams(q); + } + + @Override + public void setFragment(String f) { + // DME2 does not implement this + } + + @Override + public void send() throws APIException { + try { + if(payload!=null) { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + payload.transfer(baos); + client.setPayload(new String(baos.toByteArray())); + } else { + client.setPayload(""); + } + client.send(); + } catch (DME2Exception e) { + throw new APIException(e); + } catch (IOException e) { + throw new APIException(e); + } + } + + + public class DFuture extends Future { + protected final DME2RestfulHandler reply; + protected ResponseInfo info; + + public DFuture(DME2RestfulHandler reply) { + this.reply = reply; + } + + protected boolean evalInfo() throws APIException{ + //return info.getCode()==200; + return true; + }; + + public final boolean get(int timeout) throws CadiException { + try { + info = reply.getResponse(timeout); + ss.setLastResponse(info.getCode()); + return evalInfo(); + } catch (Exception e) { + throw new CadiException(e); + } + } + + @Override + public int code() { + return info.getCode(); + } + + @Override + public String body() { + return info.getBody(); + } + + @Override + public String header(String tag) { + return info.header(tag); + } + + } + + @Override + public Future futureCreate(Class t) { + return new DFuture(replyHandler) { + public boolean evalInfo() throws APIException { + + return info.getCode()==201; + } + }; + } + + + @Override + public Future futureReadString() { + return new DFuture(replyHandler) { + public boolean evalInfo() throws APIException { + if(info.getCode()==200) { + value = info.getBody(); + return true; + } + return false; + } + }; + } + + @Override + public Future futureRead(final RosettaDF df, final Data.TYPE type) { + return new DFuture(replyHandler) { + public boolean evalInfo() throws APIException { + if(info.getCode()==200) { + value = df.newData().in(type).load(info.getBody()).asObject(); + return true; + } + return false; + } + }; + } + + @Override + public Future future(final T t) { + return new DFuture(replyHandler) { + public boolean evalInfo() { + if(info.getCode()==200) { + value = t; + return true; + } + return false; + } + }; + } + + @Override + public Future future(HttpServletResponse resp,int expected) throws APIException { + // TODO Auto-generated method stub + return null; + } + + public void setProxy(boolean isProxy) { + this.isProxy=isProxy; + } + + +} diff --git a/client/src/main/java/com/att/cadi/dme2/DME2BasicAuth.java b/client/src/main/java/com/att/cadi/dme2/DME2BasicAuth.java new file mode 100644 index 0000000..988c92f --- /dev/null +++ b/client/src/main/java/com/att/cadi/dme2/DME2BasicAuth.java @@ -0,0 +1,64 @@ +/******************************************************************************* + * ============LICENSE_START==================================================== + * * org.onap.aai + * * =========================================================================== + * * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * * Copyright © 2017 Amdocs + * * =========================================================================== + * * 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==================================================== + * * + * * ECOMP is a trademark and service mark of AT&T Intellectual Property. + * * + ******************************************************************************/ +package com.att.cadi.dme2; + +import java.io.IOException; +import java.security.GeneralSecurityException; + +import com.att.aft.dme2.api.DME2Client; +import com.att.cadi.Access; +import com.att.cadi.CadiException; +import com.att.cadi.client.AbsBasicAuth; +import com.att.cadi.config.Config; +import com.att.cadi.config.SecurityInfoC; +import com.att.cadi.principal.BasicPrincipal; + +public class DME2BasicAuth extends AbsBasicAuth { + public DME2BasicAuth(String user, String pass, SecurityInfoC si) throws IOException { + super(user,pass,si); + } + + public DME2BasicAuth(Access access, SecurityInfoC si) throws IOException { + super(access.getProperty(Config.AAF_MECHID, null), + access.decrypt(access.getProperty(Config.AAF_MECHPASS, null), false), + si); + } + + public DME2BasicAuth(BasicPrincipal bp,SecurityInfoC si) throws IOException { + super(bp.getName(),new String(bp.getCred()),si); + } + + public DME2BasicAuth(Access access) throws IOException, GeneralSecurityException { + super(access.getProperty(Config.AAF_MECHID, null), + access.decrypt(access.getProperty(Config.AAF_MECHPASS, null), false), + new SecurityInfoC(access)); + } + + public void setSecurity(DME2Client client) throws CadiException { + if(isDenied()) { + throw new CadiException(REPEAT_OFFENDER); + } + client.addHeader("Authorization", headValue); + } +} diff --git a/client/src/main/java/com/att/cadi/dme2/DME2ClientSS.java b/client/src/main/java/com/att/cadi/dme2/DME2ClientSS.java new file mode 100644 index 0000000..f64367b --- /dev/null +++ b/client/src/main/java/com/att/cadi/dme2/DME2ClientSS.java @@ -0,0 +1,65 @@ +/******************************************************************************* + * ============LICENSE_START==================================================== + * * org.onap.aai + * * =========================================================================== + * * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * * Copyright © 2017 Amdocs + * * =========================================================================== + * * 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==================================================== + * * + * * ECOMP is a trademark and service mark of AT&T Intellectual Property. + * * + ******************************************************************************/ +package com.att.cadi.dme2; + +import java.io.IOException; + +import com.att.aft.dme2.api.DME2Client; +import com.att.cadi.Access; +import com.att.cadi.Access.Level; +import com.att.cadi.SecuritySetter; + +public class DME2ClientSS implements SecuritySetter { + private Access access; + private String user,crd; + + public DME2ClientSS(Access access, String user, String pass) throws IOException { + this.access = access; + this.user = user; + this.crd = pass; + } + + @Override + public void setSecurity(DME2Client client) { + try { + client.setCredentials(user, access.decrypt(crd, false)); + } catch (IOException e) { + access.log(Level.ERROR,e,"Error decrypting DME2 Password"); + } + } + + /* (non-Javadoc) + * @see com.att.cadi.SecuritySetter#getID() + */ + @Override + public String getID() { + return user; + } + + @Override + public int setLastResponse(int respCode) { + // TODO Auto-generated method stub + return 0; + } +} diff --git a/client/src/main/java/com/att/cadi/dme2/DME2Locator.java b/client/src/main/java/com/att/cadi/dme2/DME2Locator.java new file mode 100644 index 0000000..b81cf4a --- /dev/null +++ b/client/src/main/java/com/att/cadi/dme2/DME2Locator.java @@ -0,0 +1,349 @@ +/******************************************************************************* + * ============LICENSE_START==================================================== + * * org.onap.aai + * * =========================================================================== + * * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * * Copyright © 2017 Amdocs + * * =========================================================================== + * * 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==================================================== + * * + * * ECOMP is a trademark and service mark of AT&T Intellectual Property. + * * + ******************************************************************************/ +package com.att.cadi.dme2; + + +import java.net.InetAddress; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.UnknownHostException; +import java.util.Arrays; +import java.util.Comparator; +import java.util.Random; + +// +import com.att.aft.dme2.api.DME2Exception; +import com.att.aft.dme2.api.DME2Manager; +import com.att.aft.dme2.api.DME2Server; +import com.att.aft.dme2.manager.registry.DME2Endpoint; +import com.att.cadi.Access; +import com.att.cadi.Access.Level; +import com.att.cadi.Locator; +import com.att.cadi.LocatorException; + +public class DME2Locator implements Locator { + private DME2Manager dm; + private DME2Endpoint[] endpoints; + private Access access; + private String service; + private String version; + private String routeOffer; + private String envContext; + private String thisMachine; + private String pathInfo; + private int thisPort; + private boolean removeSelf; + private final static Random random = new Random(); + + // Default is to not bother trying to remove self + public DME2Locator(Access access, DME2Manager dm, String service, String version, String envContext, String routeOffer) throws DME2Exception, UnknownHostException, LocatorException { + this(access,dm,service,version,envContext,routeOffer,false); + } + + public DME2Locator(Access access, DME2Manager dm, String service, String version, String envContext, String routeOffer, boolean removeSelf) throws DME2Exception, UnknownHostException, LocatorException { + this.access = access; + if(dm==null) { + this.dm = new DME2Manager("DME2Locator created DME2Manager",System.getProperties()); + } else { + this.dm = dm; + } + this.service = service; + this.version = version; + this.envContext = envContext; + this.routeOffer = routeOffer; + refresh(); + DME2Server server = dm.getServer(); + if(server == null) { + thisMachine = InetAddress.getLocalHost().getHostName(); + thisPort = 0; + } else { + try { + thisMachine = server.getServerProperties().getHostname(); + //thisPort = server.getPort(); + thisPort = server.getServerProperties().getPort(); + } catch(NullPointerException np) { // BAD BOY, DME2... + access.log(Level.ERROR, "WARNING: DME2 threw a NullPointer Exception getting Server Machine and Port"); + thisMachine = InetAddress.getLocalHost().getHostName(); + thisPort = 0; + } + } + this.removeSelf = removeSelf; + } + + // Default is to not bother trying to remove self + public DME2Locator(Access access, DME2Manager dm, String aafurl) throws DME2Exception, UnknownHostException, LocatorException { + this(access,dm,aafurl,false); + } + + public DME2Locator(Access access, DME2Manager dm, String aafurl, boolean removeSelf) throws DME2Exception, UnknownHostException, LocatorException { + if(aafurl==null) throw new LocatorException("URL is null"); + this.access = access; + if(dm==null) { + dm = this.dm = new DME2Manager("DME2Locator created DME2Manager",System.getProperties()); + } else { + this.dm = dm; + } + String[] split = aafurl.split("/"); + StringBuilder sb = new StringBuilder(); + boolean dme2Entered = false; + for(String s : split) { + if(s.startsWith( "service=")) this.service = s.substring(8); + else if(s.startsWith("version=")) this.version = s.substring(8); + else if(s.startsWith("envContext=")) this.envContext = s.substring(11); + else if(s.startsWith("routeOffer=")) { + this.routeOffer = s.substring(11); + dme2Entered = true; + } + else if(dme2Entered) { + sb.append('/'); + sb.append(s); + } + pathInfo = sb.toString(); + } + DME2Server server = dm.getServer(); + if(server == null) { + thisMachine = InetAddress.getLocalHost().getHostName(); + thisPort = 0; + } else { + thisMachine = server.getServerProperties().getHostname(); + if(thisMachine==null) { // even if server !=null, apparently, it can be uninitialized + thisMachine = InetAddress.getLocalHost().getHostName(); + thisPort = 0; + } else { + try { + thisPort = server.getServerProperties().getPort(); + } catch (Exception e) { + thisPort = 0; + } + } + } + this.removeSelf=removeSelf; + refresh(); + } + + @Override + public boolean refresh() { + try { + dm.refresh(); + endpoints = dm.findEndpoints(service, version, envContext, routeOffer, true); + if(removeSelf) { + for(int i=0;i0; + } + + @Override + public void invalidate(Locator.Item item) throws LocatorException { + if(item instanceof Item) { + int idx = ((Item)item).idx; + if(idx () { + @Override + public int compare(DoubIndex a, DoubIndex b) { + if(a.db.d) return 1; + return (random.nextInt()%1)==0?1:0;// randomize if the same + } + + }); + return new Item(remote[0].idx); + } + } + } + + private class DoubIndex { + public final double d; + public final int idx; + + public DoubIndex(double doub, int i) { + d = doub; + idx = i; + } + } + @Override + public Item first() { + if(endpoints==null)return null; + for(int i=0;i { + + public DME2TransferSS(Principal principal, String app, SecurityInfoC si) throws IOException { + super(principal, app, si); + } + + @Override + public void setSecurity(DME2Client client) throws CadiException { + if(value!=null) { + if(defSS==null) { + throw new CadiException("Need App Credentials to send message"); + } + defSS.setSecurity(client); + client.addHeader(Config.CADI_USER_CHAIN, value); + } + } + + @Override + public int setLastResponse(int respCode) { + return 0; + } +} diff --git a/client/src/main/java/com/att/cadi/dme2/DME2x509SS.java b/client/src/main/java/com/att/cadi/dme2/DME2x509SS.java new file mode 100644 index 0000000..f60f791 --- /dev/null +++ b/client/src/main/java/com/att/cadi/dme2/DME2x509SS.java @@ -0,0 +1,68 @@ +/******************************************************************************* + * ============LICENSE_START==================================================== + * * org.onap.aai + * * =========================================================================== + * * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * * Copyright © 2017 Amdocs + * * =========================================================================== + * * 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==================================================== + * * + * * ECOMP is a trademark and service mark of AT&T Intellectual Property. + * * + ******************************************************************************/ +package com.att.cadi.dme2; + +import java.io.IOException; +import java.security.cert.CertificateEncodingException; + +import com.att.aft.dme2.api.DME2Client; +import com.att.cadi.CadiException; +import com.att.cadi.SecuritySetter; +import com.att.cadi.config.Config; +import com.att.cadi.config.SecurityInfoC; +import com.att.inno.env.APIException; + + +public class DME2x509SS implements SecuritySetter { + private String alias; + + public DME2x509SS(final String sendAlias, SecurityInfoC si) throws APIException, IOException, CertificateEncodingException { + if((alias=sendAlias) == null) { + if(si.default_alias == null) { + throw new APIException("JKS Alias is required to use X509SS Security. Use " + Config.CADI_ALIAS +" to set default alias"); + } else { + alias = si.default_alias; + } + } + } + + @Override + public void setSecurity(DME2Client dme2) throws CadiException { + // DME2Client has to have properties set before creation to work. + } + + /* (non-Javadoc) + * @see com.att.cadi.SecuritySetter#getID() + */ + @Override + public String getID() { + return alias; + } + + @Override + public int setLastResponse(int respCode) { + return 0; + } + +} diff --git a/client/src/main/java/com/att/cadi/dme2/DRcli.java b/client/src/main/java/com/att/cadi/dme2/DRcli.java new file mode 100644 index 0000000..9ff56ca --- /dev/null +++ b/client/src/main/java/com/att/cadi/dme2/DRcli.java @@ -0,0 +1,142 @@ +/******************************************************************************* + * ============LICENSE_START==================================================== + * * org.onap.aai + * * =========================================================================== + * * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * * Copyright © 2017 Amdocs + * * =========================================================================== + * * 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==================================================== + * * + * * ECOMP is a trademark and service mark of AT&T Intellectual Property. + * * + ******************************************************************************/ +package com.att.cadi.dme2; + +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.ArrayList; +import java.util.List; + +import com.att.aft.dme2.api.DME2Client; +import com.att.aft.dme2.api.DME2Exception; +import com.att.aft.dme2.api.DME2Manager; +import com.att.aft.dme2.manager.registry.DME2Endpoint; +import com.att.aft.dme2.request.DmeUniformResource; +import com.att.cadi.CadiException; +import com.att.cadi.SecuritySetter; +import com.att.cadi.client.EClient; +import com.att.cadi.client.Rcli; +import com.att.inno.env.APIException; +import com.att.inno.env.Data.TYPE; + +/** + * DME2 Rosetta Client + * + * JAXB defined JSON or XML over DME2 middleware + * + * + * @param + */ +public class DRcli extends Rcli { + // Can be more efficient if tied to manager, apparently. Can pass in null. + DME2Manager manager=null; + private SecuritySetter ss; + private boolean isProxy; + + public DRcli(URI uri, SecuritySetter secSet) { + this.uri = uri; + type = TYPE.JSON; + apiVersion = null; + ss=secSet; + } + + @Override + protected DRcli clone(URI uri, SecuritySetter ss) { + return new DRcli(uri,ss); + } + + + + /** + * Note from Thaniga on 11/5. DME2Client is not expected to be reused... need a fresh one + * on each transaction, which is expected to cover the Async aspects. + * + * @return + * @throws APIException + * @throws DME2Exception + */ + protected EClient client() throws CadiException { + try { + DEClient dc = new DEClient(manager,getSecuritySetter(),uri,readTimeout); + dc.setProxy(isProxy); + return dc; + } catch (DME2Exception e) { + throw new CadiException(e); + } + } + + public DRcli setManager(DME2Manager dme2Manager) { + manager = dme2Manager; + return this; + } + + public List all() throws DME2Exception, APIException { + ArrayList al = new ArrayList(); + + if(manager == null) { + manager = DME2Manager.getDefaultInstance(); + } + try { + DME2Endpoint[] endp = manager.getEndpoints(new DmeUniformResource(manager.getConfig(),uri)); + // Convert Searchable Endpoints to Direct Endpoints + for(DME2Endpoint de : endp) { + al.add(new DRcli( + new URI(uri.getScheme(),null,de.getHost(),de.getPort(),null,null,null),ss) +// new URI(uri.getScheme(),null,de.getHost(),de.getPort(),uri.getPath(),null,null),ss) + .setManager(manager) + ); + } + } catch (MalformedURLException e) { + throw new APIException("Invalid URL",e); + } catch (URISyntaxException e) { + throw new APIException("Invalid URI",e); + } + return al; + } + + @Override + public void invalidate() throws CadiException { + try { + manager.refresh(); + } catch (Exception e) { + throw new CadiException(e); + } + } + + @Override + public void setSecuritySetter(SecuritySetter ss) { + this.ss = ss; + } + + @Override + public SecuritySetter getSecuritySetter() { + return ss; + } + + public void setProxy(boolean isProxy) { + this.isProxy = isProxy; + } + +} diff --git a/client/src/main/java/com/att/cadi/dnsloc/DNSLocator.java b/client/src/main/java/com/att/cadi/dnsloc/DNSLocator.java new file mode 100644 index 0000000..498b013 --- /dev/null +++ b/client/src/main/java/com/att/cadi/dnsloc/DNSLocator.java @@ -0,0 +1,168 @@ +/******************************************************************************* + * ============LICENSE_START==================================================== + * * org.onap.aai + * * =========================================================================== + * * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * * Copyright © 2017 Amdocs + * * =========================================================================== + * * 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==================================================== + * * + * * ECOMP is a trademark and service mark of AT&T Intellectual Property. + * * + ******************************************************************************/ +package com.att.cadi.dnsloc; + +import java.io.IOException; +import java.net.InetAddress; +import java.net.URI; +import java.net.URISyntaxException; + +import com.att.cadi.Access; +import com.att.cadi.Access.Level; +import com.att.cadi.Locator; +import com.att.cadi.LocatorException; + +public class DNSLocator implements Locator { + private static enum Status {UNTRIED, OK, INVALID, SLOW}; + private static final int CHECK_TIME = 3000; + + private String host, protocol; + private Access access; + private Host[] hosts; + private int startPort, endPort; + private String suffix; + + public DNSLocator(Access access, String protocol, String host, String range) { + this.host = host; + this.protocol = protocol; + this.access = access; + int dash = range.indexOf('-'); + if(dash<0) { + startPort = endPort = Integer.parseInt(range); + } else { + startPort = Integer.parseInt(range.substring(0,dash)); + endPort = Integer.parseInt(range.substring(dash + 1)); + } + refresh(); + } + + @Override + public URI get(Item item) throws LocatorException { + return hosts[((DLItem)item).cnt].uri; + } + + @Override + public boolean hasItems() { + for(Host h : hosts) { + if(h.status==Status.OK) { + return true; + } + } + return false; + } + + @Override + public void invalidate(Item item) { + DLItem di = (DLItem)item; + hosts[di.cnt].status = Status.INVALID; + } + + @Override + public Item best() throws LocatorException { + // not a good "best" + for(int i=0;i { + public HBasicAuthSS(Access access, SecurityInfoC si) throws IOException { + super(access.getProperty(Config.AAF_MECHID, null), + access.decrypt(access.getProperty(Config.AAF_MECHPASS, null), false), + si); + } + + public HBasicAuthSS(String user, String pass, SecurityInfoC si) throws IOException { + super(user,pass,si); + } + + public HBasicAuthSS(String user, String pass, SecurityInfoC si, boolean asDefault) throws IOException { + super(user,pass,si); + if(asDefault) { + si.set(this); + } + } + + public HBasicAuthSS(BasicPrincipal bp, SecurityInfoC si) throws IOException { + super(bp.getName(),new String(bp.getCred()),si); + } + + public HBasicAuthSS(BasicPrincipal bp, SecurityInfoC si, boolean asDefault) throws IOException { + super(bp.getName(),new String(bp.getCred()),si); + if(asDefault) { + si.set(this); + } + } + + @Override + public void setSecurity(HttpURLConnection huc) throws CadiException { + if(isDenied()) { + throw new CadiException(REPEAT_OFFENDER); + } + huc.addRequestProperty("Authorization" , headValue); + if(securityInfo!=null && huc instanceof HttpsURLConnection) { + securityInfo.setSocketFactoryOn((HttpsURLConnection)huc); + } + } +} diff --git a/client/src/main/java/com/att/cadi/http/HClient.java b/client/src/main/java/com/att/cadi/http/HClient.java new file mode 100644 index 0000000..d17dcc7 --- /dev/null +++ b/client/src/main/java/com/att/cadi/http/HClient.java @@ -0,0 +1,434 @@ +/******************************************************************************* + * ============LICENSE_START==================================================== + * * org.onap.aai + * * =========================================================================== + * * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * * Copyright © 2017 Amdocs + * * =========================================================================== + * * 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==================================================== + * * + * * ECOMP is a trademark and service mark of AT&T Intellectual Property. + * * + ******************************************************************************/ +package com.att.cadi.http; + +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.Reader; +import java.net.HttpURLConnection; +import java.net.URI; +import java.net.URL; +import java.util.ArrayList; + +import javax.servlet.http.HttpServletResponse; + +import com.att.cadi.CadiException; +import com.att.cadi.LocatorException; +import com.att.cadi.SecuritySetter; +import com.att.cadi.client.EClient; +import com.att.cadi.client.Future; +import com.att.cadi.client.Rcli; +import com.att.inno.env.APIException; +import com.att.inno.env.Data; +import com.att.inno.env.Data.TYPE; +import com.att.inno.env.util.Pool.Pooled; +import com.att.rosetta.env.RosettaDF; + +/** + * Low Level Http Client Mechanism. Chances are, you want the high level "HRcli" + * for Rosetta Object Translation + * + * + */ +public class HClient implements EClient { + private URI uri; + private ArrayList
headers; + private String meth; + private String pathinfo; + private String query; + private String fragment; + private Transfer transfer; + private SecuritySetter ss; + private HttpURLConnection huc; + private int connectTimeout; + + public HClient(SecuritySetter ss, URI uri,int connectTimeout) throws LocatorException { + if (uri == null) { + throw new LocatorException("No Service available to call"); + } + this.uri = uri; + this.ss = ss; + this.connectTimeout = connectTimeout; + pathinfo = query = fragment = ""; + } + + @Override + public void setMethod(String meth) { + this.meth = meth; + } + + @Override + public void setPathInfo(String pathinfo) { + this.pathinfo = pathinfo; + } + + @Override + public void setPayload(Transfer transfer) { + this.transfer = transfer; + } + + @Override + public void addHeader(String tag, String value) { + if (headers == null) + headers = new ArrayList
(); + headers.add(new Header(tag, value)); + } + + @Override + public void setQueryParams(String q) { + query = q; + } + + @Override + public void setFragment(String f) { + fragment = f; + } + + @Override + public void send() throws APIException { + try { + // Build URL from given URI plus current Settings + if(uri.getPath()==null) { + throw new APIException("Invalid URL entered for HClient"); + } + StringBuilder pi = new StringBuilder(uri.getPath()); + if(!pathinfo.startsWith("/")) { + pi.append('/'); + } + pi.append(pathinfo); + URL url = new URI( + uri.getScheme(), + uri.getUserInfo(), + uri.getHost(), + uri.getPort(), + pi.toString(), + query, + fragment).toURL(); + pathinfo=null; + query=null; + fragment=null; + huc = (HttpURLConnection) url.openConnection(); + if(ss!=null) { + ss.setSecurity(huc); + } + huc.setRequestMethod(meth); + if (headers != null) + for (Header d : headers) { + huc.addRequestProperty(d.tag, d.value); + } + huc.setDoInput(true); + huc.setDoOutput(true); + huc.setUseCaches(false); + huc.setConnectTimeout(connectTimeout); + huc.connect(); + if (transfer != null) { + transfer.transfer(huc.getOutputStream()); + } + // TODO other settings? There's a bunch here. + } catch (Exception e) { + throw new APIException(e); + } finally { // ensure all these are reset after sends + meth=pathinfo=null; + if(headers!=null) { + headers.clear(); + } + pathinfo = query = fragment = ""; + } + } + + public abstract class HFuture extends Future { + protected HttpURLConnection huc; + protected int respCode; + protected String respMessage; + protected IOException exception; + protected StringBuilder errContent; + + public HFuture(final HttpURLConnection huc) { + this.huc = huc; + } + + protected boolean evalInfo(HttpURLConnection huc) throws APIException, IOException{ + return respCode == 200; + }; + + @Override + public final boolean get(int timeout) throws CadiException { + try { + huc.setReadTimeout(timeout); + respCode = huc.getResponseCode(); + ss.setLastResponse(respCode); + if(evalInfo(huc)) { + return true; + } else { + extractError(); + return false; + } + } catch (IOException | APIException e) { + throw new CadiException(e); + } finally { + close(); + } + } + + private void extractError() { + InputStream is = huc.getErrorStream(); + try { + if(is==null) { + is = huc.getInputStream(); + } + if(is!=null) { + errContent = new StringBuilder(); + int c; + while((c=is.read())>=0) { + errContent.append((char)c); + } + } + } catch (IOException e) { + exception = e; + } + } + + // Typically only used by Read + public StringBuilder inputStreamToString(InputStream is) { + // Avoids Carriage returns, and is reasonably efficient, given + // the buffer reads. + try { + StringBuilder sb = new StringBuilder(); + Reader rdr = new InputStreamReader(is); + try { + char[] buf = new char[256]; + int read; + while ((read = rdr.read(buf)) >= 0) { + sb.append(buf, 0, read); + } + } finally { + rdr.close(); + } + return sb; + } catch (IOException e) { + exception = e; + return null; + } + } + + + @Override + public int code() { + return respCode; + } + + public HttpURLConnection huc() { + return huc; + } + + public IOException exception() { + return exception; + } + + public String respMessage() { + return respMessage; + } + + @Override + public String header(String tag) { + return huc.getHeaderField(tag); + } + + public void close() { + if(huc!=null) { + huc.disconnect(); + } + } + } + + @Override + public Future futureCreate(Class t) { + return new HFuture(huc) { + public boolean evalInfo(HttpURLConnection huc) { + return respCode==201; + } + + @Override + public String body() { + if (errContent != null) { + return errContent.toString(); + + } else if (respMessage != null) { + return respMessage; + } + return ""; + } + }; + } + + @Override + public Future futureReadString() { + return new HFuture(huc) { + public boolean evalInfo(HttpURLConnection huc) throws IOException { + if (respCode == 200) { + StringBuilder sb = inputStreamToString(huc.getInputStream()); + if (sb != null) { + value = sb.toString(); + } + return true; + } + return false; + } + + @Override + public String body() { + if (value != null) { + return value; + } else if (errContent != null) { + return errContent.toString(); + } else if (respMessage != null) { + return respMessage; + } + return ""; + } + + }; + } + + @Override + public Future futureRead(final RosettaDF df, final TYPE type) { + return new HFuture(huc) { + private Data data; + + public boolean evalInfo(HttpURLConnection huc) throws APIException, IOException { + if (respCode == 200) { + data = df.newData().in(type).load(huc.getInputStream()); + value = data.asObject(); + return true; + } + return false; + } + + @Override + public String body() { + if (data != null) { + try { + return data.asString(); + } catch (APIException e) { + } + } else if (errContent != null) { + return errContent.toString(); + } else if (respMessage != null) { + return respMessage; + } + return ""; + } + }; + } + + @Override + public Future future(final T t) { + return new HFuture(huc) { + public boolean evalInfo(HttpURLConnection huc) { + if (respCode == 200) { + value = t; + return true; + } + return false; + } + + @Override + public String body() { + if (errContent != null) { + return errContent.toString(); + } else if (respMessage != null) { + return respMessage; + } + return Integer.toString(respCode); + } + }; + } + + @Override + public Future future(final HttpServletResponse resp, final int expected) throws APIException { + return new HFuture(huc) { + public boolean evalInfo(HttpURLConnection huc) throws IOException, APIException { + resp.setStatus(respCode); + int read; + InputStream is; + OutputStream os = resp.getOutputStream(); + if(respCode==expected) { + is = huc.getInputStream(); + // reuse Buffers + Pooled pbuff = Rcli.buffPool.get(); + try { + while((read=is.read(pbuff.content))>=0) { + os.write(pbuff.content,0,read); + } + } finally { + pbuff.done(); + } + return true; + } else { + is = huc.getErrorStream(); + if(is==null) { + is = huc.getInputStream(); + } + if(is!=null) { + errContent = new StringBuilder(); + Pooled pbuff = Rcli.buffPool.get(); + try { + while((read=is.read(pbuff.content))>=0) { + os.write(pbuff.content,0,read); + } + } finally { + pbuff.done(); + } + } + } + return false; + } + + @Override + public String body() { + return errContent==null?respMessage:errContent.toString(); + } + }; + } + + private static class Header { + public final String tag; + public final String value; + + public Header(String t, String v) { + this.tag = t; + this.value = v; + } + + public String toString() { + return tag + '=' + value; + } + } + + public String toString() { + return "HttpURLConnection Client configured to " + uri.toString(); + } +} diff --git a/client/src/main/java/com/att/cadi/http/HMangr.java b/client/src/main/java/com/att/cadi/http/HMangr.java new file mode 100644 index 0000000..78aff4e --- /dev/null +++ b/client/src/main/java/com/att/cadi/http/HMangr.java @@ -0,0 +1,236 @@ +/******************************************************************************* + * ============LICENSE_START==================================================== + * * org.onap.aai + * * =========================================================================== + * * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * * Copyright © 2017 Amdocs + * * =========================================================================== + * * 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==================================================== + * * + * * ECOMP is a trademark and service mark of AT&T Intellectual Property. + * * + ******************************************************************************/ +package com.att.cadi.http; + +import java.net.ConnectException; +import java.net.HttpURLConnection; +import java.net.SocketException; +import java.net.URI; +import java.net.URISyntaxException; + +import javax.net.ssl.SSLHandshakeException; + +import com.att.cadi.Access; +import com.att.cadi.Access.Level; +import com.att.cadi.Locator.Item; +import com.att.cadi.CadiException; +import com.att.cadi.Locator; +import com.att.cadi.LocatorException; +import com.att.cadi.SecuritySetter; +import com.att.cadi.client.Rcli; +import com.att.cadi.client.Retryable; +import com.att.inno.env.APIException; + +public class HMangr { + private String apiVersion; + private int readTimeout, connectionTimeout; + public final Locator loc; + private Access access; + + public HMangr(Access access, Locator loc) { + readTimeout = 10000; + connectionTimeout=3000; + this.loc = loc; + this.access = access; + } + + /** + * Reuse the same service. This is helpful for multiple calls that change service side cached data so that + * there is not a speed issue. + * + * If the service goes down, another service will be substituted, if available. + * + * @param access + * @param loc + * @param ss + * @param item + * @param retryable + * @return + * @throws URISyntaxException + * @throws Exception + */ + public RET same(SecuritySetter ss, Retryable retryable) throws APIException, CadiException, LocatorException { + RET ret = null; + boolean retry = true; + int retries = 0; + Rcli client = retryable.lastClient(); + try { + do { + // if no previous state, get the best + if(retryable.item()==null) { + retryable.item(loc.best()); + retryable.lastClient = null; + } + if(client==null) { + Item item = retryable.item(); + URI uri=loc.get(item); + if(uri==null) { + loc.invalidate(retryable.item()); + if(loc.hasItems()) { + retryable.item(loc.next(retryable.item())); + continue; + } else { + throw new LocatorException("No clients available for " + loc.toString()); + } + } + client = new HRcli(this, uri,item,ss) + .connectionTimeout(connectionTimeout) + .readTimeout(readTimeout) + .apiVersion(apiVersion); + } else { + client.setSecuritySetter(ss); + } + + retry = false; + try { + ret = retryable.code(client); + } catch (APIException | CadiException e) { + Item item = retryable.item(); + loc.invalidate(item); + retryable.item(loc.next(item)); + try { + Throwable ec = e.getCause(); + if(ec instanceof java.net.ConnectException) { + if(client!=null && ++retries<2) { + access.log(Level.WARN,"Connection refused, trying next available service"); + retry = true; + } else { + throw new CadiException("Connection refused, no more available connections to try"); + } + } else if(ec instanceof SSLHandshakeException) { + retryable.item(null); + throw e; + } else if(ec instanceof SocketException) { + if("java.net.SocketException: Connection reset".equals(ec.getMessage())) { + access.log(Level.ERROR, ec.getMessage(), " can mean Certificate Expiration or TLS Protocol issues"); + } + retryable.item(null); + throw e; + } else { + retryable.item(null); + throw e; + } + } finally { + client = null; + } + } catch (ConnectException e) { + Item item = retryable.item(); + loc.invalidate(item); + retryable.item(loc.next(item)); + } + } while(retry); + } finally { + retryable.lastClient = client; + } + return ret; + } + + + public RET best(SecuritySetter ss, Retryable retryable) throws LocatorException, CadiException, APIException { + if(loc==null) { + throw new LocatorException("No Locator Configured"); + } + retryable.item(loc.best()); + return same(ss,retryable); + } + public RET all(SecuritySetter ss, Retryable retryable) throws LocatorException, CadiException, APIException { + return oneOf(ss,retryable,true,null); + } + + public RET all(SecuritySetter ss, Retryable retryable,boolean notify) throws LocatorException, CadiException, APIException { + return oneOf(ss,retryable,notify,null); + } + + public RET oneOf(SecuritySetter ss, Retryable retryable,boolean notify,String host) throws LocatorException, CadiException, APIException { + RET ret = null; + // make sure we have all current references: + loc.refresh(); + for(Item li=loc.first();li!=null;li=loc.next(li)) { + URI uri=loc.get(li); + if(host!=null && !host.equals(uri.getHost())) { + break; + } + try { + ret = retryable.code(new HRcli(this,uri,li,ss)); + access.log(Level.DEBUG,"Success calling",uri,"during call to all services"); + } catch (APIException | CadiException e) { + Throwable t = e.getCause(); + if(t!=null && t instanceof ConnectException) { + loc.invalidate(li); + access.log(Level.ERROR,"Connection to",uri,"refused during call to all services"); + } else if(t instanceof SSLHandshakeException) { + access.log(Level.ERROR,t.getMessage()); + loc.invalidate(li); + } else if(t instanceof SocketException) { + if("java.net.SocketException: Connection reset".equals(t.getMessage())) { + access.log(Level.ERROR, t.getMessage(), " can mean Certificate Expiration or TLS Protocol issues"); + } + retryable.item(null); + throw e; + } else { + throw e; + } + } catch (ConnectException e) { + loc.invalidate(li); + access.log(Level.ERROR,"Connection to",uri,"refused during call to all services"); + } + } + + if(ret == null && notify) + throw new LocatorException("No available clients to call"); + return ret; + } + + + public void close() { + // TODO Anything here? + } + + public HMangr readTimeout(int timeout) { + this.readTimeout = timeout; + return this; + } + + public int readTimeout() { + return readTimeout; + } + + public void connectionTimeout(int t) { + connectionTimeout = t; + } + + public int connectionTimout() { + return connectionTimeout; + } + + public HMangr apiVersion(String version) { + apiVersion = version; + return this; + } + + public String apiVersion() { + return apiVersion; + } + +} diff --git a/client/src/main/java/com/att/cadi/http/HRcli.java b/client/src/main/java/com/att/cadi/http/HRcli.java new file mode 100644 index 0000000..a55b55a --- /dev/null +++ b/client/src/main/java/com/att/cadi/http/HRcli.java @@ -0,0 +1,134 @@ +/******************************************************************************* + * ============LICENSE_START==================================================== + * * org.onap.aai + * * =========================================================================== + * * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * * Copyright © 2017 Amdocs + * * =========================================================================== + * * 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==================================================== + * * + * * ECOMP is a trademark and service mark of AT&T Intellectual Property. + * * + ******************************************************************************/ +package com.att.cadi.http; + +import java.net.HttpURLConnection; +import java.net.URI; +import java.net.URISyntaxException; + +import com.att.aft.dme2.api.DME2Exception; +import com.att.cadi.CadiException; +import com.att.cadi.LocatorException; +import com.att.cadi.SecuritySetter; +import com.att.cadi.Locator.Item; +import com.att.cadi.client.EClient; +import com.att.cadi.client.Rcli; +import com.att.inno.env.APIException; +import com.att.inno.env.Data.TYPE; + +/** + * DME2 Rosetta Client + * + * JAXB defined JSON or XML over DME2 middleware + * + * + * @param + */ +public class HRcli extends Rcli { + private HMangr hman; + private Item item; + private SecuritySetter ss; + + public HRcli(HMangr hman, Item locItem, SecuritySetter secSet) throws URISyntaxException, LocatorException { + item=locItem; + uri=hman.loc.get(locItem); + this.hman = hman; + ss=secSet; + type = TYPE.JSON; + apiVersion = hman.apiVersion(); + } + + public HRcli(HMangr hman, URI uri, Item locItem, SecuritySetter secSet) { + locItem=item; + this.uri = uri; + this.hman = hman; + ss=secSet; + type = TYPE.JSON; + apiVersion = hman.apiVersion(); + } + + @Override + protected HRcli clone(URI uri, SecuritySetter ss) { + return new HRcli(hman,uri,item,ss); + } + + + + /** + * Note from Thaniga on 11/5. DME2Client is not expected to be reused... need a fresh one + * on each transaction, which is expected to cover the Async aspects. + * + * @return + * @throws APIException + * @throws DME2Exception + */ + protected EClient client() throws CadiException { + try { + if(uri==null) { + Item item = hman.loc.best(); + if(item==null) { + throw new CadiException("No service available for " + hman.loc.toString()); + } + uri = hman.loc.get(item); + } + return new HClient(ss,uri,connectionTimeout); + } catch (Exception e) { + throw new CadiException(e); + } + } + + /* (non-Javadoc) + * @see com.att.cadi.client.Rcli#setSecuritySetter(com.att.cadi.SecuritySetter) + */ + @Override + public void setSecuritySetter(SecuritySetter ss) { + this.ss = ss; + } + + /* (non-Javadoc) + * @see com.att.cadi.client.Rcli#getSecuritySetter() + */ + @Override + public SecuritySetter getSecuritySetter() { + return ss; + } + + public void invalidate() throws CadiException { + try { + hman.loc.invalidate(item); + } catch (Exception e) { + throw new CadiException(e); + } + } + + public HRcli setManager(HMangr hman) { + this.hman = hman; + return this; + } + + public String toString() { + return uri.toString(); + } + +} diff --git a/client/src/main/java/com/att/cadi/http/HTransferSS.java b/client/src/main/java/com/att/cadi/http/HTransferSS.java new file mode 100644 index 0000000..180a341 --- /dev/null +++ b/client/src/main/java/com/att/cadi/http/HTransferSS.java @@ -0,0 +1,66 @@ +/******************************************************************************* + * ============LICENSE_START==================================================== + * * org.onap.aai + * * =========================================================================== + * * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * * Copyright © 2017 Amdocs + * * =========================================================================== + * * 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==================================================== + * * + * * ECOMP is a trademark and service mark of AT&T Intellectual Property. + * * + ******************************************************************************/ +package com.att.cadi.http; + +import java.io.IOException; +import java.net.HttpURLConnection; +import java.security.Principal; + +import javax.net.ssl.HttpsURLConnection; + +import com.att.cadi.CadiException; +import com.att.cadi.client.AbsTransferSS; +import com.att.cadi.config.Config; +import com.att.cadi.config.SecurityInfoC; + + +public class HTransferSS extends AbsTransferSS { + public HTransferSS(Principal principal, String app) throws IOException { + super(principal, app); + } + + public HTransferSS(Principal principal, String app, SecurityInfoC si) { + super(principal, app, si); + } + + @Override + public void setSecurity(HttpURLConnection huc) throws CadiException { + if(value!=null) { + if(defSS==null) { + throw new CadiException("Need App Credentials to send message"); + } + defSS.setSecurity(huc); + huc.addRequestProperty(Config.CADI_USER_CHAIN, value); + } + if(securityInfo!=null) { + securityInfo.setSocketFactoryOn((HttpsURLConnection)huc); + } + } + + @Override + public int setLastResponse(int respCode) { + return 0; + } + +} diff --git a/client/src/main/java/com/att/cadi/http/HX509SS.java b/client/src/main/java/com/att/cadi/http/HX509SS.java new file mode 100644 index 0000000..3022c0f --- /dev/null +++ b/client/src/main/java/com/att/cadi/http/HX509SS.java @@ -0,0 +1,168 @@ +/******************************************************************************* + * ============LICENSE_START==================================================== + * * org.onap.aai + * * =========================================================================== + * * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * * Copyright © 2017 Amdocs + * * =========================================================================== + * * 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==================================================== + * * + * * ECOMP is a trademark and service mark of AT&T Intellectual Property. + * * + ******************************************************************************/ +package com.att.cadi.http; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.net.HttpURLConnection; +import java.security.PrivateKey; +import java.security.SecureRandom; +import java.security.Signature; +import java.security.cert.CertificateEncodingException; +import java.security.cert.X509Certificate; + +import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.X509KeyManager; + +import com.att.cadi.CadiException; +import com.att.cadi.SecuritySetter; +import com.att.cadi.Symm; +import com.att.cadi.config.Config; +import com.att.cadi.config.SecurityInfoC; +import com.att.inno.env.APIException; +import com.att.inno.env.util.Chrono; + + +public class HX509SS implements SecuritySetter { + private static final byte[] X509 = "x509 ".getBytes(); + private PrivateKey priv; + private byte[] pub; + private String cert; + private SecurityInfoC securityInfo; + private String algo; + private String alias; + private static int count = new SecureRandom().nextInt(); + + public HX509SS(SecurityInfoC si) throws APIException, IOException, CertificateEncodingException { + this(null,si,false); + } + + public HX509SS(SecurityInfoC si, boolean asDefault) throws APIException, IOException, CertificateEncodingException { + this(null,si,asDefault); + } + + public HX509SS(final String sendAlias, SecurityInfoC si) throws APIException, IOException, CertificateEncodingException { + this(sendAlias, si, false); + } + + public HX509SS(final String sendAlias, SecurityInfoC si, boolean asDefault) throws APIException, IOException, CertificateEncodingException { + securityInfo = si; + if((alias=sendAlias) == null) { + if(si.default_alias == null) { + throw new APIException("JKS Alias is required to use X509SS Security. Use " + Config.CADI_ALIAS +" to set default alias"); + } else { + alias = si.default_alias; + } + } + + priv=null; + X509KeyManager[] xkms = si.getKeyManagers(); + if(xkms==null || xkms.length==0) { + throw new APIException("There are no valid keys available in given Keystores. Wrong Keypass? Expired?"); + } + for(int i=0;priv==null&&i0) { + algo = chain[0].getSigAlgName(); + pub = chain[0].getEncoded(); + ByteArrayOutputStream baos = new ByteArrayOutputStream(pub.length*2); + ByteArrayInputStream bais = new ByteArrayInputStream(pub); + Symm.base64noSplit.encode(bais,baos,X509); + cert = baos.toString(); + + /* + // Inner Test code, uncomment if fix needed + bais = new ByteArrayInputStream(baos.toByteArray()); + baos = new ByteArrayOutputStream(input.length*2); + Symm.base64noSplit().decode(bais,baos,5); + byte[] output = baos.toByteArray(); + String reconstitute = output.toString(); + System.out.println("ok"); + CertificateFactory certFactory; + try { + bais = new ByteArrayInputStream(output); + certFactory = CertificateFactory.getInstance("X.509"); + X509Certificate x509 = (X509Certificate)certFactory.generateCertificate(bais); + System.out.println(x509.toString()); + } catch (CertificateException e) { + e.printStackTrace(); + } + */ + } + } + if(algo==null) { + throw new APIException("X509 Security Setter not configured"); + } + } + + @Override + public void setSecurity(HttpURLConnection huc) throws CadiException { + if(huc instanceof HttpsURLConnection) { + securityInfo.setSocketFactoryOn((HttpsURLConnection)huc); + } + if(alias==null) { // must be a one-way + huc.setRequestProperty("Authorization", cert); + + // Test Signed content + try { + String data = "SignedContent["+ inc() + ']' + Chrono.dateTime(); + huc.setRequestProperty("Data", data); + + Signature sig = Signature.getInstance(algo); + sig.initSign(priv); + sig.update(data.getBytes()); + byte[] signature = sig.sign(); + + ByteArrayOutputStream baos = new ByteArrayOutputStream((int)(signature.length*1.3)); + ByteArrayInputStream bais = new ByteArrayInputStream(signature); + Symm.base64noSplit.encode(bais, baos); + huc.setRequestProperty("Signature", new String(baos.toByteArray())); + + } catch (Exception e) { + throw new CadiException(e); + } + } + } + + private synchronized int inc() { + return ++count; + } + + /* (non-Javadoc) + * @see com.att.cadi.SecuritySetter#getID() + */ + @Override + public String getID() { + return alias; + } + + @Override + public int setLastResponse(int respCode) { + return 0; + } +} diff --git a/client/src/main/java/com/att/cadi/locator/DME2Locator.java b/client/src/main/java/com/att/cadi/locator/DME2Locator.java new file mode 100644 index 0000000..72a5f73 --- /dev/null +++ b/client/src/main/java/com/att/cadi/locator/DME2Locator.java @@ -0,0 +1,346 @@ +/******************************************************************************* + * ============LICENSE_START==================================================== + * * org.onap.aai + * * =========================================================================== + * * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * * Copyright © 2017 Amdocs + * * =========================================================================== + * * 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==================================================== + * * + * * ECOMP is a trademark and service mark of AT&T Intellectual Property. + * * + ******************************************************************************/ +package com.att.cadi.locator; + + +import java.net.InetAddress; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.UnknownHostException; +import java.util.Arrays; +import java.util.Comparator; +import java.util.Properties; +import java.util.Random; +import java.security.SecureRandom; + +//import com.att.aft.dme2.api.DME2Endpoint; +import com.att.aft.dme2.api.DME2Exception; +import com.att.aft.dme2.api.DME2Manager; +import com.att.aft.dme2.api.DME2Server; +import com.att.aft.dme2.manager.registry.DME2Endpoint; +import com.att.cadi.Access; +import com.att.cadi.Access.Level; +import com.att.cadi.Locator; +import com.att.cadi.LocatorException; +import com.att.cadi.PropAccess; + +public class DME2Locator implements Locator { + private DME2Manager dm; + private DME2Endpoint[] endpoints; + private Access access; + private String service; + private String version; + private String routeOffer; + private String envContext; + private String thisMachine; + private String pathInfo; + private int thisPort; + private boolean removeSelf; + private final static SecureRandom random = new SecureRandom(); + + // Default is to not bother trying to remove self + public DME2Locator(Access access, DME2Manager dm, String service, String version, String envContext, String routeOffer) throws DME2Exception, UnknownHostException, LocatorException { + this(access,dm,service,version,envContext,routeOffer,false); + } + + public DME2Locator(Access access, DME2Manager dm, String service, String version, String envContext, String routeOffer, boolean removeSelf) throws DME2Exception, UnknownHostException, LocatorException { + this.access = access; + if(dm==null) { + this.dm = new DME2Manager("DME2Locator created DME2Manager",System.getProperties()); + } else { + this.dm = dm; + } + this.service = service; + this.version = version; + this.envContext = envContext; + this.routeOffer = routeOffer; + refresh(); + if(thisMachine==null) { + // Can't get from dm... + thisMachine = InetAddress.getLocalHost().getHostName(); + thisPort = 0; + } else { + thisPort = dm.getPort(); + } + + this.removeSelf = removeSelf; + } + + // Default is to not bother trying to remove self + public DME2Locator(Access access, DME2Manager dm, String aafurl) throws DME2Exception, UnknownHostException, LocatorException { + this(access,dm,aafurl,false); + } + + public DME2Locator(Access access, DME2Manager dm, String aafurl, boolean removeSelf) throws DME2Exception, UnknownHostException, LocatorException { + if(aafurl==null) { + throw new LocatorException("URL is null"); + } + this.access = access; + if(dm==null) { + Properties dprops; + if(access instanceof PropAccess) { + dprops = ((PropAccess)access).getDME2Properties(); + } else { + dprops = System.getProperties(); + } + dm = this.dm = new DME2Manager("DME2Locator created DME2Manager",dprops); + } else { + this.dm = dm; + } + String[] split = aafurl.split("/"); + StringBuilder sb = new StringBuilder(); + boolean dme2Entered = false; + for(String s : split) { + if(s.startsWith("service=")) { + this.service = s.substring(8); + } else if(s.startsWith("version=")) { + this.version = s.substring(8); + } else if(s.startsWith("envContext=")) { + this.envContext = s.substring(11); + } else if(s.startsWith("routeOffer=")) { + this.routeOffer = s.substring(11); + dme2Entered = true; + } else if(dme2Entered) { + sb.append('/'); + sb.append(s); + } + } + pathInfo = sb.toString(); + thisMachine = dm.getHostname(); + if(thisMachine==null) { + // Can't get from dm... + thisMachine = InetAddress.getLocalHost().getHostName(); + thisPort = 0; + } else { + thisPort = dm.getPort(); + } + this.removeSelf=removeSelf; + refresh(); + } + + @Override + public boolean refresh() { + try { + dm.refresh(); + //endpoints = dm.findEndpoints(service, version, envContext, routeOffer, true); + if(removeSelf) { +// for(int i=0;i0; + return true; + } + + @Override + public void invalidate(Locator.Item item) throws LocatorException { + if(item instanceof DME2Item) { + int idx = ((DME2Item)item).idx; +// if(idx () { + @Override + public int compare(DoubIndex a, DoubIndex b) { + if(a.db.d) return 1; + return (random.nextInt()%1)==0?1:0;// randomize if the same + } + + }); + return new DME2Item(remote[0].idx); + } + } + } + + private static class DoubIndex { + public final double d; + public final int idx; + + public DoubIndex(double doub, int i) { + d = doub; + idx = i; + } + } + @Override + public DME2Item first() { +// if(endpoints==null)return null; +// for(int i=0;i { + private static enum Status {UNTRIED, OK, INVALID, SLOW}; + private static final int CHECK_TIME = 3000; + + private String host, protocol; + private Access access; + private Host[] hosts; + private int startPort, endPort; + private String suffix; + + public DNSLocator(Access access, String protocol, String host, String range) { + this.host = host; + this.protocol = protocol; + this.access = access; + int dash = range.indexOf('-'); + if(dash<0) { + startPort = endPort = Integer.parseInt(range); + } else { + startPort = Integer.parseInt(range.substring(0,dash)); + endPort = Integer.parseInt(range.substring(dash + 1)); + } + refresh(); + } + + @Override + public URI get(Item item) throws LocatorException { + return hosts[((DLItem)item).cnt].uri; + } + + @Override + public boolean hasItems() { + for(Host h : hosts) { + if(h.status==Status.OK) { + return true; + } + } + return false; + } + + @Override + public void invalidate(Item item) { + DLItem di = (DLItem)item; + hosts[di.cnt].status = Status.INVALID; + } + + @Override + public Item best() throws LocatorException { + // not a good "best" + for(int i=0;i { + private final HX509SS ss; + + public HClientHotPeerLocator(Access access, String urlstr, long invalidateTime, String localLatitude, + String localLongitude, HX509SS ss) throws LocatorException { + super(access, urlstr, invalidateTime, localLatitude, localLongitude); + + this.ss = ss; + } + + @Override + protected HClient _newClient(String clientInfo) throws LocatorException { + try { + int idx = clientInfo.indexOf('/'); + return new HClient(ss,new URI("https://"+(idx<0?clientInfo:clientInfo.substring(0, idx))),3000); + } catch (URISyntaxException e) { + throw new LocatorException(e); + } + } + + @Override + protected HClient _invalidate(HClient client) { + return null; + } + + @Override + protected void _destroy(HClient client) { + } +} diff --git a/client/src/main/java/com/att/cadi/locator/HotPeerLocator.java b/client/src/main/java/com/att/cadi/locator/HotPeerLocator.java new file mode 100644 index 0000000..f8a1546 --- /dev/null +++ b/client/src/main/java/com/att/cadi/locator/HotPeerLocator.java @@ -0,0 +1,304 @@ +/******************************************************************************* + * ============LICENSE_START==================================================== + * * org.onap.aai + * * =========================================================================== + * * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * * Copyright © 2017 Amdocs + * * =========================================================================== + * * 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==================================================== + * * + * * ECOMP is a trademark and service mark of AT&T Intellectual Property. + * * + ******************************************************************************/ +package com.att.cadi.locator; + +import com.att.cadi.Access; +import com.att.cadi.Access.Level; +import com.att.cadi.Locator; +import com.att.cadi.LocatorException; +import com.att.cadi.routing.GreatCircle; +import com.att.inno.env.util.Split; + +/** + * This Locator is to handle Hot Peer load protection, when the Servers are + * 1) Static + * 2) Well known client URL + * + * The intention is to change traffic over to the Hot Peer, if a server goes down, and reinstate + * when it is back up. + * + * Example of this kind of Service is a MS Certificate Server + * + * + * + * @param + */ +public abstract class HotPeerLocator implements Locator { + private final String[] urlstrs; + private final CLIENT[] clients; + private final long[] failures; + private final double[] distances; + private int preferred; + private long invalidateTime; + private Thread refreshThread; + protected Access access; + + /** + * Construct: Expect one or more Strings in the form: + * 192.555.112.223:39/38.88087/-77.30122 + * separated by commas + * + * @param trans + * @param urlstr + * @param invalidateTime + * @param localLatitude + * @param localLongitude + * @throws LocatorException + */ + @SuppressWarnings("unchecked") + protected HotPeerLocator(Access access, final String urlstr, final long invalidateTime, final String localLatitude, final String localLongitude) throws LocatorException { + this.access = access; + urlstrs = Split.split(',', urlstr); + clients = (CLIENT[])new Object[urlstrs.length]; + failures = new long[urlstrs.length]; + distances= new double[urlstrs.length]; + this.invalidateTime = invalidateTime; + + double distance = Double.MAX_VALUE; + for(int i=0;iSystem.currentTimeMillis()) { + throw new LocatorException("Client requested is invalid"); + } else { + synchronized(clients) { + c = _newClient(urlstrs[hpi.idx]); + failures[hpi.idx]=0L; + } + } + } else if(failures[hpi.idx]>0){ + throw new LocatorException("Client requested is invalid"); + } + return c; + } + + public String info(Item item) { + HPItem hpi = (HPItem)item; + if(hpi!=null && hpi.idx=clients.length) { + return null; + } + return hpi; + } + + @Override + public boolean refresh() { + boolean force = !hasItems(); // If no Items at all, reset + boolean rv = true; + long now = System.currentTimeMillis(); + for(int i=0;i0L && (failures[i] { + private final URI [] orig; + private PLItem[] current; + private int end; + private final SecureRandom random; + private URI[] resolved; + private long lastRefreshed=0L; + private long minRefresh; + private long backgroundRefresh; + + public PropertyLocator(String locList) throws LocatorException { + this(locList,10000L, 1000*60*20); // defaults, do not refresh more than once in 10 seconds, Refresh Locator every 20 mins. + } + /** + * comma delimited root url list + * + * @param locList + * @throws LocatorException + */ + public PropertyLocator(String locList, long minRefreshMillis, long backgroundRefreshMillis) throws LocatorException { + minRefresh = minRefreshMillis; + backgroundRefresh = backgroundRefreshMillis; + if(locList==null) { + throw new LocatorException("No Location List given for PropertyLocator"); + } + String[] locarray = Split.split(',',locList); + List uriList = new ArrayList(); + + random = new SecureRandom(); + + for(int i=0;i0?current[0]:null; + } + + @Override + public boolean hasItems() { + return end>0; + } + + @Override + public Item next(Item item) throws LocatorException { + if(item==null) { + return null; + } else { + int spot; + if((spot=(((PLItem)item).order+1))>=end)return null; + return current[spot]; + } + } + + @Override + public synchronized void invalidate(Item item) throws LocatorException { + if(--end<=0) { + refresh(); + return; + } + PLItem pli = (PLItem)item; + int i,order; + for(i=0;ilastRefreshed) { + // Build up list + List resolve = new ArrayList(); + String realname; + for(int i = 0; i < orig.length ; ++i) { + try { + InetAddress ia[] = InetAddress.getAllByName(orig[i].getHost()); + + URI o,n; + for(int j=0;j0?args[0]:"xx9999"); + System.out.printf("Path: %s\n",path); + client.addHeader("Accept", "application/Perms+json;q=1.0;charset=utf-8;version=2.0,application/json;q=1.0;version=2.0,*"); + client.setMethod("GET"); + client.setContext(path); + client.setPayload("");// Note: Even on "GET", you need a String in DME2 + + String o = client.sendAndWait(5000); // There are other Asynchronous call options, see DME2 Docs + if(o==null) { + System.out.println('[' + o + ']' + " (blank is good)"); + } + + + } catch (Exception e) { + e.printStackTrace(); + } + } + +} diff --git a/client/src/test/java/com/client/test/JU_DNSLocator.java b/client/src/test/java/com/client/test/JU_DNSLocator.java new file mode 100644 index 0000000..fcd14c8 --- /dev/null +++ b/client/src/test/java/com/client/test/JU_DNSLocator.java @@ -0,0 +1,58 @@ +/******************************************************************************* + * ============LICENSE_START==================================================== + * * org.onap.aai + * * =========================================================================== + * * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * * Copyright © 2017 Amdocs + * * =========================================================================== + * * 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==================================================== + * * + * * ECOMP is a trademark and service mark of AT&T Intellectual Property. + * * + ******************************************************************************/ +package com.client.test; + +import java.net.URI; +import java.net.URL; +import java.net.URLConnection; + +import org.junit.AfterClass; +import org.junit.Test; + +import com.att.cadi.locator.DNSLocator; +import com.att.cadi.PropAccess; +import com.att.cadi.Locator.Item; + +public class JU_DNSLocator { + + @AfterClass + public static void tearDownAfterClass() throws Exception { + } + + @Test + public void test() { + + DNSLocator dl = new DNSLocator(new PropAccess(), "https", "aaf.it.att.com","8150-8152"); + try { + Item item = dl.best(); + URI uri = dl.get(item); + URL url = uri.toURL(); + URLConnection conn = url.openConnection(); + conn.connect(); + } catch (Exception e) { + e.printStackTrace(); + } + } + +} diff --git a/client/src/test/java/com/client/test/JU_PropertyLocator.java b/client/src/test/java/com/client/test/JU_PropertyLocator.java new file mode 100644 index 0000000..be8e587 --- /dev/null +++ b/client/src/test/java/com/client/test/JU_PropertyLocator.java @@ -0,0 +1,99 @@ +/******************************************************************************* + * ============LICENSE_START==================================================== + * * org.onap.aai + * * =========================================================================== + * * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * * Copyright © 2017 Amdocs + * * =========================================================================== + * * 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==================================================== + * * + * * ECOMP is a trademark and service mark of AT&T Intellectual Property. + * * + ******************************************************************************/ +package com.client.test; + +import java.net.URI; + +import org.junit.AfterClass; +import org.junit.Test; + +import static org.junit.Assert.*; + +import com.att.cadi.Locator.Item; +import com.att.cadi.locator.PropertyLocator; + +public class JU_PropertyLocator { + + @AfterClass + public static void tearDownAfterClass() throws Exception { + } + + @Test + public void test() throws Exception { + PropertyLocator pl = new PropertyLocator("https://localhost:2345,https://fred.wilma.com:26444,https://tom.jerry.com:534"); + + Item i; + int count; + boolean print = false; + for(int j=0;j<900000;++j) { + count = 0; + for(i = pl.first();i!=null;i=pl.next(i)) { + URI loc = pl.get(i); + if(print)System.out.println(loc.toString()); + ++count; + } + assertEquals(3,count); + assertTrue(pl.hasItems()); + if(print)System.out.println("---"); + pl.invalidate(pl.best()); + + count = 0; + for(i = pl.first();i!=null;i=pl.next(i)) { + URI loc = pl.get(i); + if(print)System.out.println(loc.toString()); + ++count; + } + + assertEquals(2,count); + assertTrue(pl.hasItems()); + if(print)System.out.println("---"); + pl.invalidate(pl.best()); + + count = 0; + for(i = pl.first();i!=null;i=pl.next(i)) { + URI loc = pl.get(i); + if(print)System.out.println(loc.toString()); + ++count; + } + + assertEquals(1,count); + assertTrue(pl.hasItems()); + if(print)System.out.println("---"); + pl.invalidate(pl.best()); + + count = 0; + for(i = pl.first();i!=null;i=pl.next(i)) { + URI loc = pl.get(i); + if(print)System.out.println(loc.toString()); + ++count; + } + + assertEquals(0,count); + assertFalse(pl.hasItems()); + + pl.refresh(); + } + } + +} diff --git a/client/src/test/java/com/client/test/PaulUzee.java b/client/src/test/java/com/client/test/PaulUzee.java new file mode 100644 index 0000000..6f82146 --- /dev/null +++ b/client/src/test/java/com/client/test/PaulUzee.java @@ -0,0 +1,146 @@ +/******************************************************************************* + * ============LICENSE_START==================================================== + * * org.onap.aai + * * =========================================================================== + * * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * * Copyright © 2017 Amdocs + * * =========================================================================== + * * 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==================================================== + * * + * * ECOMP is a trademark and service mark of AT&T Intellectual Property. + * * + ******************************************************************************/ +package com.client.test; + +import java.io.IOException; +import java.io.InputStream; +import java.io.PrintStream; +import java.net.URI; +import java.util.Properties; + +import com.att.aft.dme2.api.DME2Manager; +import com.att.cadi.Access; +import com.att.cadi.Locator; +import com.att.cadi.Access.Level; +import com.att.cadi.Locator.Item; +import com.att.cadi.dme2.DME2Locator; + +public class PaulUzee { + public static void main(String[] args) { + try { + // You'll want to put this on Command line "-D" probably + Properties props = System.getProperties(); + props.put("AFT_LATITUDE","32.780140"); + props.put("AFT_LONGITUDE","-96.800451"); + props.put("AFT_ENVIRONMENT","AFTPRD"); + + // + // Use an "Access" class to hook up logging, properties, etc. + // Make one that ties into your code's logging, property mechanism, etc. + // + Access access = new PaulAccess(); + + DME2Manager dm = new DME2Manager("Paul Uzee's Test",props); + Locator loc = new DME2Locator(access ,dm,"com.att.authz.AuthorizationService","2.0","PROD","DEFAULT"); + + + for(Item item = loc.first(); item!=null; item=loc.next(item)) { + URI location = (URI) loc.get(item); + access.log(Level.INFO,location); + access.log(Level.INFO,location.getScheme()); + access.log(Level.INFO,location.getHost()); + access.log(Level.INFO, location.getPort()); + } + } catch (Exception e) { + e.printStackTrace(); + } + + } + + private static class PaulAccess implements Access { + private Level willWrite = Level.INFO; + + @Override + public ClassLoader classLoader() { + return getClass().getClassLoader(); + } + + @Override + public String decrypt(String data, boolean def) throws IOException { + return data; + } + + @Override + public String getProperty(String tag, String def) { + return System.getProperty(tag, def); + } + + @Override + public void load(InputStream is) throws IOException { + System.getProperties().load(is); + } + + @Override + public void log(Level level, Object... obj) { + if(level.compareTo(willWrite)<0) return; + PrintStream ps; + switch(level) { + case DEBUG: + case AUDIT: + case ERROR: + case WARN: + ps = System.err; + break; + case INFO: + case INIT: + default: + ps = System.out; + } + boolean first = true; + for(Object o : obj) { + if(first)first=false; + else ps.print(' '); + ps.print(o.toString()); + } + ps.println(); + } + + @Override + public void log(Exception e, Object... obj) { + Object[] objs = new Object[obj.length+1]; + objs[0]=e.getMessage(); + System.arraycopy(objs, 1, obj, 0, obj.length); + log(Level.ERROR,e,objs); + } + + @Override + public void setLogLevel(Level l) { + willWrite = l; + } + + /* (non-Javadoc) + * @see com.att.cadi.Access#willLog(com.att.cadi.Access.Level) + */ + @Override + public boolean willLog(Level level) { + return true; + } + + @Override + public void printf(Level level, String fmt, Object... elements) { + // TODO Auto-generated method stub + + } + }; +} diff --git a/client/src/test/java/com/client/test/TestAccess.java b/client/src/test/java/com/client/test/TestAccess.java new file mode 100644 index 0000000..3724f1b --- /dev/null +++ b/client/src/test/java/com/client/test/TestAccess.java @@ -0,0 +1,91 @@ +/******************************************************************************* + * ============LICENSE_START==================================================== + * * org.onap.aai + * * =========================================================================== + * * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * * Copyright © 2017 Amdocs + * * =========================================================================== + * * 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==================================================== + * * + * * ECOMP is a trademark and service mark of AT&T Intellectual Property. + * * + ******************************************************************************/ +package com.client.test; + +import java.io.IOException; +import java.io.InputStream; + +import com.att.cadi.Access; +import com.att.cadi.Symm; + +public class TestAccess implements Access { + private Symm symm; + + public TestAccess() { + symm = Symm.obtain(this); + } + + public void log(Level level, Object... elements) { + boolean first = true; + for(int i=0;i ft = client.read("/authz/nss/com.att.aaf","text/json"); + if(ft.get(10000)) { + System.out.println("Hurray,\n"+ft.body()); + } else { + System.out.println("not quite: " + ft.code()); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + +} diff --git a/client/src/test/java/com/client/test/TestHClient.java b/client/src/test/java/com/client/test/TestHClient.java new file mode 100644 index 0000000..0c6a162 --- /dev/null +++ b/client/src/test/java/com/client/test/TestHClient.java @@ -0,0 +1,84 @@ +/******************************************************************************* + * ============LICENSE_START==================================================== + * * org.onap.aai + * * =========================================================================== + * * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * * Copyright © 2017 Amdocs + * * =========================================================================== + * * 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==================================================== + * * + * * ECOMP is a trademark and service mark of AT&T Intellectual Property. + * * + ******************************************************************************/ +package com.client.test; + +import java.net.HttpURLConnection; +import java.net.URI; +import java.util.Properties; + +import com.att.aft.dme2.api.DME2Manager; +import com.att.cadi.CadiException; +import com.att.cadi.Locator; +import com.att.cadi.Locator.Item; +import com.att.cadi.PropAccess; +import com.att.cadi.SecuritySetter; +import com.att.cadi.client.Future; +import com.att.cadi.client.Rcli; +import com.att.cadi.client.Retryable; +import com.att.cadi.config.Config; +import com.att.cadi.config.SecurityInfoC; +import com.att.cadi.http.HBasicAuthSS; +import com.att.cadi.http.HMangr; +import com.att.cadi.locator.DME2Locator; +import com.att.inno.env.APIException; + +public class TestHClient { + public static void main(String[] args) { + try { + PropAccess access = new PropAccess(); + DME2Manager dm = new DME2Manager("DME2Manager TestHClient",access.getProperties()); + Locator loc = new DME2Locator(access,dm,"com.att.authz.AuthorizationService","2.0","DEV","BAU_SE"); + + for(Item item = loc.first(); item!=null; item=loc.next(item)) { + System.out.println(loc.get(item)); + } + + + SecurityInfoC si = new SecurityInfoC(access); + SecuritySetter ss = new HBasicAuthSS("m12345@aaf.att.com", + access.decrypt("enc:7K6yjLQqha_S9yApkIul2K_by5Moemcos1HRAVnhMXu",false), si); +// SecuritySetter ss = new X509SS(si, "aaf"); + + HMangr hman = new HMangr(access,loc); + try { + hman.best(ss, new Retryable() { + @Override + public Void code(Rcli cli) throws APIException, CadiException { + Future ft = cli.read("/authz/nss/com.att.aaf","text/json"); + if(ft.get(10000)) { + System.out.println("Hurray,\n"+ft.body()); + } else { + System.out.println("not quite: " + ft.code()); + } + return null; + }}); + } finally { + hman.close(); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + +} -- cgit 1.2.3-korg