Public and Private Locate entries
[aaf/authz.git] / cadi / client / src / main / java / org / onap / aaf / cadi / http / HMangr.java
1 /**
2  * ============LICENSE_START====================================================
3  * org.onap.aaf
4  * ===========================================================================
5  * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
6  * ===========================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  * 
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  * 
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ============LICENSE_END====================================================
19  *
20  */
21
22 package org.onap.aaf.cadi.http;
23
24 import java.net.ConnectException;
25 import java.net.HttpURLConnection;
26 import java.net.SocketException;
27 import java.net.URI;
28 import java.net.URISyntaxException;
29
30 import javax.net.ssl.SSLHandshakeException;
31
32 import org.onap.aaf.cadi.Access;
33 import org.onap.aaf.cadi.Access.Level;
34 import org.onap.aaf.cadi.CadiException;
35 import org.onap.aaf.cadi.Locator;
36 import org.onap.aaf.cadi.Locator.Item;
37 import org.onap.aaf.cadi.LocatorException;
38 import org.onap.aaf.cadi.SecuritySetter;
39 import org.onap.aaf.cadi.client.Rcli;
40 import org.onap.aaf.cadi.client.Retryable;
41 import org.onap.aaf.cadi.util.FixURIinfo;
42 import org.onap.aaf.misc.env.APIException;
43
44 public class HMangr {
45     private String apiVersion;
46     private int readTimeout, connectionTimeout;
47     public final Locator<URI> loc;
48     private Access access;
49     
50     public HMangr(Access access, Locator<URI> loc) throws LocatorException {
51         readTimeout = 10000;
52         connectionTimeout=3000;
53         if (loc ==  null) {
54             throw new LocatorException("Null Locator passed");
55         }
56         this.loc = loc;
57         this.access = access;
58     }
59
60     /**
61      * Reuse the same service.  This is helpful for multiple calls that change service side cached data so that 
62      * there is not a speed issue.
63      * 
64      * If the service goes down, another service will be substituted, if available.
65      * 
66      * @param access
67      * @param loc
68      * @param ss
69      * @param item
70      * @param retryable
71      * @return
72      * @throws URISyntaxException 
73      * @throws Exception
74      */
75     public<RET> RET same(SecuritySetter<HttpURLConnection> ss, Retryable<RET> retryable) throws APIException, CadiException, LocatorException {
76         RET ret = null;
77         boolean retry = true;
78         Rcli<HttpURLConnection> client = retryable.lastClient();
79         try {
80             do {
81                 Item item;
82                 // if no previous state, get the best
83                 if (retryable.item()==null) {
84                     item = loc.best();
85                     if (item==null) {
86                         throw new LocatorException("No Services Found for " + loc);
87                     }
88                     retryable.item(item);
89                     retryable.lastClient = null;
90                 }
91                 if (client==null) {
92                     item = retryable.item();
93                     URI uri=loc.get(item);
94                     if (uri==null) {
95                         loc.invalidate(retryable.item());
96                         if (loc.hasItems()) {
97                             retryable.item(loc.next(retryable.item()));
98                             continue;
99                         } else {
100                             throw new LocatorException("No clients available for " + loc.toString());
101                         }
102                     }
103                     client = new HRcli(this, uri,item,ss)
104                         .connectionTimeout(connectionTimeout)
105                         .readTimeout(readTimeout)
106                         .apiVersion(apiVersion);
107                 } else {
108                     client.setSecuritySetter(ss);
109                 }
110                 
111                 retry = false;
112                 try {
113                     ret = retryable.code(client);
114                 } catch (APIException | CadiException e) {
115                     item = retryable.item();
116                     loc.invalidate(item);
117                     retryable.item(loc.next(item));
118                     try {
119                         Throwable ec = e.getCause();
120                         if (ec instanceof java.net.ConnectException) {
121                             if (client!=null && loc.hasItems()) { 
122                                 access.log(Level.WARN,"Connection refused, trying next available service");
123                                 retry = true;
124                             } else {
125                                 throw new CadiException("Connection refused, no more services to try");
126                             }
127                         } else if (ec instanceof java.net.SocketException) {
128                             if (client!=null && loc.hasItems()) { 
129                                 access.log(Level.WARN,"Socket prematurely closed, trying next available service");
130                                 retry = true;
131                             } else {
132                                 throw new CadiException("Socket prematurely closed, no more services to try");
133                             }
134                         } else if (ec instanceof SocketException) {
135                             if ("java.net.SocketException: Connection reset".equals(ec.getMessage())) {
136                                 access.log(Level.ERROR, ec.getMessage(), " can mean Certificate Expiration or TLS Protocol issues");
137                             }
138                             retryable.item(null);
139                             throw e;
140                         } else {
141                             retryable.item(null);
142                             throw e;
143                         }
144                     } finally {
145                         client = null;
146                     }
147                 } catch (ConnectException e) {
148                     item = retryable.item();
149                     loc.invalidate(item);
150                     retryable.item(loc.next(item));
151                 }
152             } while (retry);
153         } finally {
154             retryable.lastClient = client;
155         }
156         return ret;
157     }
158     
159     
160     public<RET> RET best(SecuritySetter<HttpURLConnection> ss, Retryable<RET> retryable) throws LocatorException, CadiException, APIException {
161         retryable.item(loc.best());
162         return same(ss,retryable);
163     }
164     public<RET> RET all(SecuritySetter<HttpURLConnection> ss, Retryable<RET> retryable) throws LocatorException, CadiException, APIException {
165         return oneOf(ss,retryable,true,null);
166     }
167
168     public<RET> RET all(SecuritySetter<HttpURLConnection> ss, Retryable<RET> retryable,boolean notify) throws LocatorException, CadiException, APIException {
169         return oneOf(ss,retryable,notify,null);
170     }
171     
172     public<RET> RET oneOf(SecuritySetter<HttpURLConnection> ss, Retryable<RET> retryable,boolean notify,String host) throws LocatorException, CadiException, APIException {
173         RET ret = null;
174         // make sure we have all current references:
175         loc.refresh();
176         for (Item li=loc.first();li!=null;li=loc.next(li)) {
177             URI uri=loc.get(li);
178             FixURIinfo fui = new FixURIinfo(uri);
179             if (host!=null && !host.equals(fui.getHost())) {
180                 break;
181             }
182             try {
183                 ret = retryable.code(new HRcli(this,uri,li,ss));
184                 access.log(Level.DEBUG,"Success calling",uri,"during call to all services");
185             } catch (APIException | CadiException e) {
186                 Throwable t = e.getCause();
187                 if (t!=null && t instanceof ConnectException) {
188                     loc.invalidate(li);
189                     access.log(Level.ERROR,"Connection to",uri,"refused during call to all services");
190                 } else if (t instanceof SSLHandshakeException) {
191                     access.log(Level.ERROR,t.getMessage());
192                     loc.invalidate(li);
193                 } else if (t instanceof SocketException) {
194                     if ("java.net.SocketException: Connection reset".equals(t.getMessage())) {
195                         access.log(Level.ERROR, t.getMessage(), " can mean Certificate Expiration or TLS Protocol issues");
196                     }
197                     retryable.item(null);
198                     throw e;
199                 } else {
200                     throw e;
201                 }
202             } catch (ConnectException e) {
203                 loc.invalidate(li);
204                 access.log(Level.ERROR,"Connection to",uri,"refused during call to all services");
205             }
206         }
207             
208         if (ret == null && notify) 
209             throw new LocatorException("No available clients to call");
210         return ret;
211     }
212     
213
214     public void close() {
215         // TODO Anything here?
216     }
217
218     public HMangr readTimeout(int timeout) {
219         this.readTimeout = timeout;
220         return this;
221     }
222
223     public int readTimeout() {
224         return readTimeout;
225     }
226     
227     public void connectionTimeout(int t) {
228         connectionTimeout = t;
229     }
230
231     public int connectionTimeout() {
232         return connectionTimeout;
233     }
234
235     public HMangr apiVersion(String version) {
236         apiVersion = version;
237         return this;
238     }
239
240     public String apiVersion() {
241         return apiVersion;
242     }
243
244 }