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 Instrumental
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 }