changed to unmaintained
[aaf/authz.git] / cadi / oauth-enduser / src / main / java / org / onap / aaf / cadi / enduser / SimpleRESTClient.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 package org.onap.aaf.cadi.enduser;
22
23 import java.io.IOException;
24 import java.io.OutputStream;
25 import java.io.PrintWriter;
26 import java.net.ConnectException;
27 import java.security.Principal;
28
29 import org.onap.aaf.cadi.CadiException;
30 import org.onap.aaf.cadi.LocatorException;
31 import org.onap.aaf.cadi.client.EClient;
32 import org.onap.aaf.cadi.client.Future;
33 import org.onap.aaf.cadi.client.Rcli;
34 import org.onap.aaf.cadi.client.Result;
35 import org.onap.aaf.cadi.client.Retryable;
36 import org.onap.aaf.cadi.config.Config;
37 import org.onap.aaf.cadi.oauth.TimedToken;
38 import org.onap.aaf.cadi.oauth.TokenClient;
39 import org.onap.aaf.cadi.oauth.TokenClientFactory;
40 import org.onap.aaf.cadi.oauth.TzClient;
41 import org.onap.aaf.cadi.principal.TaggedPrincipal;
42 import org.onap.aaf.misc.env.APIException;
43 import org.onap.aaf.misc.env.util.StringBuilderWriter;
44
45 public class SimpleRESTClient {
46         private static final String APPLICATION_JSON = "application/json";
47         private static final String[] EMPTY = new String[0];
48         private final TokenClient tokenClient;
49         private final TzClient restClient;
50         private int callTimeout;
51         private String client_id;
52         private String app;
53         private String chain;
54         private Headers headers = new Headers() {
55                 @Override
56                 public String[] headers() {
57                         return EMPTY;
58                 }};
59         
60         public SimpleRESTClient(final TokenClientFactory tcf, final String tokenURL, final String endpoint, final String[] scope) throws CadiException, LocatorException, APIException {
61                 callTimeout = Integer.parseInt(tcf.access.getProperty(Config.AAF_CALL_TIMEOUT,Config.AAF_CALL_TIMEOUT_DEF));
62                 tokenClient = tcf.newClient(tokenURL);
63                 Result<TimedToken> rtt = tokenClient.getToken(scope);
64                 if(rtt.isOK()) {
65                         restClient = tcf.newTzClient(endpoint);
66                         
67                         if((client_id = tcf.access.getProperty(Config.AAF_APPID, null))==null) {
68                                 if((client_id = tcf.access.getProperty(Config.CADI_ALIAS, null))==null) {
69                                         throw new CadiException(Config.AAF_APPID + " or " + Config.CADI_ALIAS + " needs to be defined");
70                                 }                               
71                         }
72                         try {
73                                 restClient.setToken(client_id,rtt.value);
74                         } catch (IOException e) {
75                                 throw new CadiException(e);
76                         }
77                 } else {
78                         throw new CadiException(rtt.error);
79                 }
80         }
81         
82         public SimpleRESTClient timeout(int newTimeout) {
83                 callTimeout = newTimeout;
84                 return this;
85         }
86
87         //Format:<ID>:<APP>:<protocol>[:AS][,<ID>:<APP>:<protocol>]*
88         public SimpleRESTClient endUser(Principal principal) {
89                 if(principal==null) {
90                         chain = null;
91                 } else {
92                         if(principal instanceof TaggedPrincipal) {
93                                 TaggedPrincipal tp = (TaggedPrincipal)principal;
94                                 chain = tp.getName() + ':' + (app==null?"":app) + ':' + tp.tag() + ":AS";
95                         } else {
96                                 chain = principal.getName() + (app==null?"":':'+app);
97                         }
98                 }
99                 return this;
100         }
101         
102         /**
103          * Single Threaded Class for building up content
104          * @author jg1555
105          *
106          */
107         public static class Input {
108                 private static final byte[] EMPTY_STREAM_BYTES = "".getBytes();
109
110                 private String content;
111                 private StringBuilder sb;
112                 
113                 public Input() {
114                         content = null;
115                         sb = null;
116                 }
117                 
118                 public Input(final String content) {
119                         this.content = content;
120                 }
121                 
122                 public void set(final String content) {
123                         this.content = content;
124                 }
125                 
126                 public PrintWriter writer() {
127                         return new PrintWriter(new StringBuilderWriter(builder()));
128                 }
129                 
130                 public StringBuilder builder() {
131                         if(sb==null) {
132                                 sb = new StringBuilder();
133                                 content = null;
134                         }
135                         return sb;
136                 }
137                 
138                 /**
139                  * Reuse StringBuilder object
140                  */
141                 public void clear() {
142                         content = null;
143                         if(sb!=null) {
144                                 sb.setLength(0);
145                         }
146                 }
147                 
148                 @Override
149                 public String toString() {
150                         if(content!=null) {
151                                 return content;
152                         } else if(sb!=null) {
153                                 return sb.toString();
154                         } else {
155                                 return "";
156                         }
157                 }
158
159                 public byte[] getBytes() {
160                         byte[] rv;
161                         if(content==null) {
162                                 if(sb==null) {
163                                         rv = EMPTY_STREAM_BYTES;
164                                 } else {
165                                         rv = sb.toString().getBytes();  
166                                 }
167                         } else {
168                                 rv = content.getBytes();
169                         }
170                         content = null;
171                         return rv;
172                 }
173         }
174
175         /////////////////////////////////////////////////////////////
176         //  
177         // CREATE
178         //
179         /////////////////////////////////////////////////////////////
180         public void create(final String path, final Input input) throws RESTException, CadiException, LocatorException, APIException  {
181                 post(path,APPLICATION_JSON, input);
182         }
183
184         public void post(final String path, final Input input) throws RESTException, CadiException, LocatorException, APIException  {
185                 post(path,APPLICATION_JSON, input);
186         }
187
188         public void post(final String path, final String contentType, final Input input) throws RESTException, CadiException, LocatorException, APIException  {
189                 Future<Void> future = restClient.best(new Retryable<Future<Void>>() {
190                         @Override
191                         public Future<Void> code(Rcli<?> client) throws CadiException, ConnectException, APIException {
192                                 return client.create(path, contentType, new ETransfer(input));
193                         }
194                 });
195                 if(!future.get(callTimeout)) {
196                         throw new RESTException(future);
197                 }                                       
198         }
199
200         /////////////////////////////////////////////////////////////
201         //  
202         // READ
203         //
204         /////////////////////////////////////////////////////////////
205         public String read(final String path) throws RESTException, CadiException, LocatorException, APIException  {
206                 return get(path,APPLICATION_JSON);
207         }
208
209         public String get(final String path) throws RESTException, CadiException, LocatorException, APIException  {
210                 return get(path,APPLICATION_JSON);
211         }
212
213         public String get(final String path, final String accepts) throws RESTException, CadiException, LocatorException, APIException  {
214                 Future<String> future = restClient.best(new Retryable<Future<String>>() {
215                         @Override
216                         public Future<String> code(Rcli<?> client) throws CadiException, ConnectException, APIException {
217                                 return client.read(path,accepts, headers());
218                         }
219                 });
220                 if(future.get(callTimeout)) {
221                         return future.value;
222                 } else {
223                         throw new RESTException(future);
224                 }                                       
225         }
226         
227         /////////////////////////////////////////////////////////////
228         //  
229         // UPDATE
230         //
231         /////////////////////////////////////////////////////////////
232
233         public String update(final String path, final Input input) throws RESTException, CadiException, LocatorException, APIException  {
234                 return put(path,APPLICATION_JSON, input);
235         }
236
237         public String put(final String path, final Input input) throws RESTException, CadiException, LocatorException, APIException  {
238                 return put(path,APPLICATION_JSON, input);
239         }
240
241         public String put(final String path, final String contentType, final Input input) throws RESTException, CadiException, LocatorException, APIException  {
242                 Future<String> future = restClient.best(new Retryable<Future<String>>() {
243                         @Override
244                         public Future<String> code(Rcli<?> client) throws CadiException, ConnectException, APIException {
245                                 return client.update(path, contentType, new ETransfer(input));
246                         }
247                 });
248                 if(future.get(callTimeout)) {
249                         return future.value;
250                 } else {
251                         throw new RESTException(future);
252                 }                                       
253         }
254
255         /////////////////////////////////////////////////////////////
256         //  
257         // DELETE
258         //
259         /////////////////////////////////////////////////////////////
260         public void delete(final String path) throws RESTException, CadiException, LocatorException, APIException  {
261                 delete(path,APPLICATION_JSON);
262         }
263                 
264         public void delete(final String path, final String contentType) throws RESTException, CadiException, LocatorException, APIException  {
265                 Future<Void> future = restClient.best(new Retryable<Future<Void>>() {
266                         @Override
267                         public Future<Void> code(Rcli<?> client) throws CadiException, ConnectException, APIException {
268                                 return client.delete(path, contentType);
269                         }
270                 });
271                 if(!future.get(callTimeout)) {
272                         throw new RESTException(future);
273                 }                                       
274         }
275
276         /////////////////////////////////////////////////////////////
277         
278         private static class ETransfer implements EClient.Transfer {
279                 private Input input;
280                 public ETransfer(final Input input) {
281                         this.input = input;
282                 }
283                 
284                 @Override
285                 public void transfer(OutputStream os) throws IOException, APIException {
286                         os.write(input.getBytes());
287                 }
288         }
289
290         public interface Headers {
291                 String[] headers();
292         }
293         
294         public String[] headers() {
295                 if(chain==null) {
296                         return headers.headers();
297                 } else {
298                         String[] strs = headers.headers();
299                         String[] rv = new String[strs.length+2];
300                         rv[0]=Config.CADI_USER_CHAIN;
301                         rv[1]=chain;
302                         for(int i = 0;i<strs.length;++i) {
303                                 rv[i+2]=strs[i];
304                         }
305                         return rv;
306                 }
307         }
308 }