1 /*******************************************************************************
\r
2 * ============LICENSE_START====================================================
\r
4 * * ===========================================================================
\r
5 * * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
\r
6 * * ===========================================================================
\r
7 * * Licensed under the Apache License, Version 2.0 (the "License");
\r
8 * * you may not use this file except in compliance with the License.
\r
9 * * You may obtain a copy of the License at
\r
11 * * http://www.apache.org/licenses/LICENSE-2.0
\r
13 * * Unless required by applicable law or agreed to in writing, software
\r
14 * * distributed under the License is distributed on an "AS IS" BASIS,
\r
15 * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
\r
16 * * See the License for the specific language governing permissions and
\r
17 * * limitations under the License.
\r
18 * * ============LICENSE_END====================================================
\r
20 * * ECOMP is a trademark and service mark of AT&T Intellectual Property.
\r
22 ******************************************************************************/
\r
23 package com.att.cadi.client;
\r
25 import java.io.IOException;
\r
26 import java.io.OutputStream;
\r
27 import java.net.URI;
\r
28 import java.util.Enumeration;
\r
30 import javax.servlet.ServletInputStream;
\r
31 import javax.servlet.http.HttpServletRequest;
\r
32 import javax.servlet.http.HttpServletResponse;
\r
34 import com.att.cadi.CadiException;
\r
35 import com.att.cadi.SecuritySetter;
\r
36 import com.att.inno.env.APIException;
\r
37 import com.att.inno.env.Data.TYPE;
\r
38 import com.att.inno.env.util.Pool;
\r
39 import com.att.inno.env.util.Pool.Pooled;
\r
40 import com.att.rosetta.env.RosettaDF;
\r
42 public abstract class Rcli<CT> {
\r
43 public static final String BLANK = "";
\r
44 public static final String CONTENT_TYPE = "Content-Type";
\r
45 public static final String ACCEPT = "Accept";
\r
47 protected static final String POST = "POST";
\r
48 protected static final String GET = "GET";
\r
49 protected static final String PUT = "PUT";
\r
50 protected static final String DELETE = "DELETE";
\r
51 protected TYPE type;
\r
52 protected String apiVersion;
\r
53 protected int readTimeout = 5000;
\r
54 protected int connectionTimeout = 3000;
\r
56 private String queryParams, fragment;
\r
57 public static Pool<byte[]> buffPool = new Pool<byte[]>(new Pool.Creator<byte[]>() {
\r
59 public byte[] create() throws APIException {
\r
60 return new byte[1024];
\r
64 public void destroy(byte[] t) {
\r
68 public boolean isValid(byte[] t) {
\r
73 public void reuse(byte[] t) {
\r
82 public abstract void setSecuritySetter(SecuritySetter<CT> ss);
\r
83 public abstract SecuritySetter<CT> getSecuritySetter();
\r
86 public Rcli<CT> forUser(SecuritySetter<CT> ss) {
\r
87 Rcli<CT> rv = clone(uri==null?this.uri:uri,ss);
\r
88 setSecuritySetter(ss);
\r
90 rv.apiVersion = apiVersion;
\r
94 protected abstract Rcli<CT> clone(URI uri, SecuritySetter<CT> ss);
\r
96 public abstract void invalidate() throws CadiException;
\r
98 public Rcli<CT> readTimeout(int millis) {
\r
99 readTimeout = millis;
\r
103 public Rcli<CT> connectionTimeout(int millis) {
\r
104 connectionTimeout = millis;
\r
108 public Rcli<CT> type(TYPE type) {
\r
113 public Rcli<CT> apiVersion(String apiVersion) {
\r
114 this.apiVersion = apiVersion;
\r
118 public boolean isApiVersion(String prospective) {
\r
119 return apiVersion.equals(prospective);
\r
123 public String typeString(Class<?> cls) {
\r
124 return "application/"+cls.getSimpleName()+"+"+type.name().toLowerCase()+
\r
125 (apiVersion==null?BLANK:";version="+apiVersion);
\r
128 protected abstract EClient<CT> client() throws CadiException;
\r
131 public<T> Future<T> create(String pathinfo, String contentType, final RosettaDF<T> df, final T t) throws APIException, CadiException {
\r
132 final int idx = pathinfo.indexOf('?');
\r
135 qp=pathinfo.substring(idx+1);
\r
136 pathinfo=pathinfo.substring(0,idx);
\r
140 EClient<CT> client = client();
\r
141 client.setMethod(POST);
\r
142 client.addHeader(CONTENT_TYPE,contentType);
\r
143 client.setPathInfo(pathinfo);
\r
144 client.setQueryParams(qp);
\r
145 client.setFragment(fragment);
\r
146 client.setPayload(new EClient.Transfer() {
\r
148 public void transfer(OutputStream os) throws IOException, APIException {
\r
149 df.newData().out(type).direct(t,os);
\r
153 queryParams = fragment = null;
\r
154 return client.futureCreate(df.getTypeClass());
\r
157 public<T> Future<T> create(String pathinfo, final RosettaDF<T> df, final T t) throws APIException, CadiException {
\r
158 final int idx = pathinfo.indexOf('?');
\r
161 qp=pathinfo.substring(idx+1);
\r
162 pathinfo=pathinfo.substring(0,idx);
\r
166 EClient<CT> client = client();
\r
167 client.setMethod(POST);
\r
168 client.addHeader(CONTENT_TYPE,typeString(df.getTypeClass()));
\r
169 client.setPathInfo(pathinfo);
\r
170 client.setQueryParams(qp);
\r
171 client.setFragment(fragment);
\r
172 client.setPayload(new EClient.Transfer() {
\r
174 public void transfer(OutputStream os) throws IOException, APIException {
\r
175 df.newData().out(type).direct(t,os);
\r
179 queryParams = fragment = null;
\r
180 return client.futureCreate(df.getTypeClass());
\r
183 public<T> Future<T> create(String pathinfo, Class<?> cls, final RosettaDF<T> df, final T t) throws APIException, CadiException {
\r
184 final int idx = pathinfo.indexOf('?');
\r
187 qp=pathinfo.substring(idx+1);
\r
188 pathinfo=pathinfo.substring(0,idx);
\r
193 EClient<CT> client = client();
\r
194 client.setMethod(POST);
\r
195 client.addHeader(CONTENT_TYPE,typeString(cls));
\r
196 client.setPathInfo(pathinfo);
\r
197 client.setQueryParams(qp);
\r
198 client.setFragment(fragment);
\r
199 client.setPayload(new EClient.Transfer() {
\r
201 public void transfer(OutputStream os) throws IOException, APIException {
\r
202 df.newData().out(type).direct(t,os);
\r
206 queryParams = fragment = null;
\r
207 return client.futureCreate(df.getTypeClass());
\r
210 public<T> Future<T> create(String pathinfo, Class<T> cls) throws APIException, CadiException {
\r
211 final int idx = pathinfo.indexOf('?');
\r
214 qp=pathinfo.substring(idx+1);
\r
215 pathinfo=pathinfo.substring(0,idx);
\r
220 EClient<CT> client = client();
\r
221 client.setMethod(POST);
\r
222 client.addHeader(CONTENT_TYPE,typeString(cls));
\r
223 client.setPathInfo(pathinfo);
\r
224 client.setQueryParams(qp);
\r
225 client.setFragment(fragment);
\r
226 client.setPayload(null);
\r
228 queryParams = fragment = null;
\r
229 return client.futureCreate(cls);
\r
232 public Future<Void> create(String pathinfo, String contentType) throws APIException, CadiException {
\r
233 final int idx = pathinfo.indexOf('?');
\r
236 qp=pathinfo.substring(idx+1);
\r
237 pathinfo=pathinfo.substring(0,idx);
\r
242 EClient<CT> client = client();
\r
243 client.setMethod(POST);
\r
244 client.addHeader(CONTENT_TYPE,contentType);
\r
245 client.setPathInfo(pathinfo);
\r
246 client.setQueryParams(qp);
\r
247 client.setFragment(fragment);
\r
248 client.setPayload(null);
\r
250 queryParams = fragment = null;
\r
251 return client.futureCreate(Void.class);
\r
255 public Future<String> read(String pathinfo, String accept, String ... headers) throws APIException, CadiException {
\r
256 final int idx = pathinfo.indexOf('?');
\r
259 qp=pathinfo.substring(idx+1);
\r
260 pathinfo=pathinfo.substring(0,idx);
\r
265 EClient<CT> client = client();
\r
266 client.setMethod(GET);
\r
267 client.addHeader(ACCEPT, accept);
\r
269 for(int i=1;i<headers.length;i=i+2) {
\r
270 client.addHeader(headers[i-1],headers[i]);
\r
272 client.setQueryParams(qp);
\r
273 client.setFragment(fragment);
\r
275 client.setPathInfo(pathinfo);
\r
277 client.setPayload(null);
\r
279 queryParams = fragment = null;
\r
280 return client.futureReadString();
\r
283 public<T> Future<T> read(String pathinfo, String accept, RosettaDF<T> df, String ... headers) throws APIException, CadiException {
\r
284 final int idx = pathinfo.indexOf('?');
\r
287 qp=pathinfo.substring(idx+1);
\r
288 pathinfo=pathinfo.substring(0,idx);
\r
293 EClient<CT> client = client();
\r
294 client.setMethod(GET);
\r
295 client.addHeader(ACCEPT, accept);
\r
296 for(int i=1;i<headers.length;i=i+2) {
\r
297 client.addHeader(headers[i-1],headers[i]);
\r
299 client.setQueryParams(qp);
\r
300 client.setFragment(fragment);
\r
301 client.setPathInfo(pathinfo);
\r
303 client.setPayload(null);
\r
305 queryParams = fragment = null;
\r
306 return client.futureRead(df,type);
\r
309 public<T> Future<T> read(String pathinfo, RosettaDF<T> df,String ... headers) throws APIException, CadiException {
\r
310 final int idx = pathinfo.indexOf('?');
\r
313 qp=pathinfo.substring(idx+1);
\r
314 pathinfo=pathinfo.substring(0,idx);
\r
319 EClient<CT> client = client();
\r
320 client.setMethod(GET);
\r
321 client.addHeader(ACCEPT, typeString(df.getTypeClass()));
\r
322 for(int i=1;i<headers.length;i=i+2) {
\r
323 client.addHeader(headers[i-1],headers[i]);
\r
325 client.setQueryParams(qp);
\r
326 client.setFragment(fragment);
\r
327 client.setPathInfo(pathinfo);
\r
329 client.setPayload(null);
\r
331 queryParams = fragment = null;
\r
332 return client.futureRead(df,type);
\r
335 public<T> Future<T> read(String pathinfo, Class<?> cls, RosettaDF<T> df) throws APIException, CadiException {
\r
336 final int idx = pathinfo.indexOf('?');
\r
339 qp=pathinfo.substring(idx+1);
\r
340 pathinfo=pathinfo.substring(0,idx);
\r
345 EClient<CT> client = client();
\r
346 client.setMethod(GET);
\r
347 client.addHeader(ACCEPT, typeString(cls));
\r
348 client.setQueryParams(qp);
\r
349 client.setFragment(fragment);
\r
350 client.setPathInfo(pathinfo);
\r
352 client.setPayload(null);
\r
354 queryParams = fragment = null;
\r
355 return client.futureRead(df,type);
\r
358 public<T> Future<T> update(String pathinfo, String contentType, final RosettaDF<T> df, final T t) throws APIException, CadiException {
\r
359 final int idx = pathinfo.indexOf('?');
\r
362 qp=pathinfo.substring(idx+1);
\r
363 pathinfo=pathinfo.substring(0,idx);
\r
368 EClient<CT> client = client();
\r
369 client.setMethod(PUT);
\r
370 client.addHeader(CONTENT_TYPE,contentType);
\r
371 client.setQueryParams(qp);
\r
372 client.setFragment(fragment);
\r
373 client.setPathInfo(pathinfo);
\r
374 client.setPayload(new EClient.Transfer() {
\r
376 public void transfer(OutputStream os) throws IOException, APIException {
\r
377 df.newData().out(type).direct(t,os);
\r
381 queryParams = fragment = null;
\r
382 return client.future(t);
\r
385 public<T> Future<String> updateRespondString(String pathinfo, final RosettaDF<T> df, final T t) throws APIException, CadiException {
\r
386 final int idx = pathinfo.indexOf('?');
\r
389 qp=pathinfo.substring(idx+1);
\r
390 pathinfo=pathinfo.substring(0,idx);
\r
395 EClient<CT> client = client();
\r
396 client.setMethod(PUT);
\r
397 client.addHeader(CONTENT_TYPE, typeString(df.getTypeClass()));
\r
398 client.setQueryParams(qp);
\r
399 client.setFragment(fragment);
\r
400 client.setPathInfo(pathinfo);
\r
401 client.setPayload(new EClient.Transfer() {
\r
403 public void transfer(OutputStream os) throws IOException, APIException {
\r
404 df.newData().out(type).direct(t,os);
\r
408 queryParams = fragment = null;
\r
409 return client.futureReadString();
\r
413 public<T> Future<T> update(String pathinfo, final RosettaDF<T> df, final T t) throws APIException, CadiException {
\r
414 final int idx = pathinfo.indexOf('?');
\r
417 qp=pathinfo.substring(idx+1);
\r
418 pathinfo=pathinfo.substring(0,idx);
\r
423 EClient<CT> client = client();
\r
424 client.setMethod(PUT);
\r
425 client.addHeader(CONTENT_TYPE, typeString(df.getTypeClass()));
\r
426 client.setQueryParams(qp);
\r
427 client.setFragment(fragment);
\r
428 client.setPathInfo(pathinfo);
\r
429 client.setPayload(new EClient.Transfer() {
\r
431 public void transfer(OutputStream os) throws IOException, APIException {
\r
432 df.newData().out(type).direct(t,os);
\r
436 queryParams = fragment = null;
\r
437 return client.future(t);
\r
440 public<T> Future<T> update(String pathinfo, Class<?> cls, final RosettaDF<T> df, final T t) throws APIException, CadiException {
\r
441 final int idx = pathinfo.indexOf('?');
\r
444 qp=pathinfo.substring(idx+1);
\r
445 pathinfo=pathinfo.substring(0,idx);
\r
450 EClient<CT> client = client();
\r
451 client.setMethod(PUT);
\r
452 client.addHeader(CONTENT_TYPE, typeString(cls));
\r
453 client.setQueryParams(qp);
\r
454 client.setFragment(fragment);
\r
455 client.setPathInfo(pathinfo);
\r
456 client.setPayload(new EClient.Transfer() {
\r
458 public void transfer(OutputStream os) throws IOException, APIException {
\r
459 df.newData().out(type).direct(t,os);
\r
463 queryParams = fragment = null;
\r
464 return client.future(t);
\r
468 * A method to update with a VOID
\r
473 * @throws APIException
\r
474 * @throws CadiException
\r
476 public<T> Future<Void> update(String pathinfo) throws APIException, CadiException {
\r
477 final int idx = pathinfo.indexOf('?');
\r
480 qp=pathinfo.substring(idx+1);
\r
481 pathinfo=pathinfo.substring(0,idx);
\r
486 EClient<CT> client = client();
\r
487 client.setMethod(PUT);
\r
488 client.addHeader(CONTENT_TYPE, typeString(Void.class));
\r
489 client.setQueryParams(qp);
\r
490 client.setFragment(fragment);
\r
491 client.setPathInfo(pathinfo);
\r
492 // client.setPayload(new EClient.Transfer() {
\r
494 // public void transfer(OutputStream os) throws IOException, APIException {
\r
498 queryParams = fragment = null;
\r
499 return client.future(null);
\r
502 public<T> Future<T> delete(String pathinfo, String contentType, final RosettaDF<T> df, final T t) throws APIException, CadiException {
\r
503 final int idx = pathinfo.indexOf('?');
\r
506 qp=pathinfo.substring(idx+1);
\r
507 pathinfo=pathinfo.substring(0,idx);
\r
512 EClient<CT> client = client();
\r
513 client.setMethod(DELETE);
\r
514 client.addHeader(CONTENT_TYPE, contentType);
\r
515 client.setQueryParams(qp);
\r
516 client.setFragment(fragment);
\r
517 client.setPathInfo(pathinfo);
\r
518 client.setPayload(new EClient.Transfer() {
\r
520 public void transfer(OutputStream os) throws IOException, APIException {
\r
521 df.newData().out(type).direct(t,os);
\r
525 queryParams = fragment = null;
\r
526 return client.future(t);
\r
529 public<T> Future<T> delete(String pathinfo, Class<?> cls, final RosettaDF<T> df, final T t) throws APIException, CadiException {
\r
530 final int idx = pathinfo.indexOf('?');
\r
533 qp=pathinfo.substring(idx+1);
\r
534 pathinfo=pathinfo.substring(0,idx);
\r
539 EClient<CT> client = client();
\r
540 client.setMethod(DELETE);
\r
541 client.addHeader(CONTENT_TYPE, typeString(cls));
\r
542 client.setQueryParams(qp);
\r
543 client.setFragment(fragment);
\r
544 client.setPathInfo(pathinfo);
\r
545 client.setPayload(new EClient.Transfer() {
\r
547 public void transfer(OutputStream os) throws IOException, APIException {
\r
548 df.newData().out(type).direct(t,os);
\r
552 queryParams = fragment = null;
\r
553 return client.future(t);
\r
556 public<T> Future<T> delete(String pathinfo, final RosettaDF<T> df, final T t) throws APIException, CadiException {
\r
557 final int idx = pathinfo.indexOf('?');
\r
560 qp=pathinfo.substring(idx+1);
\r
561 pathinfo=pathinfo.substring(0,idx);
\r
566 EClient<CT> client = client();
\r
567 client.setMethod(DELETE);
\r
568 client.addHeader(CONTENT_TYPE, typeString(df.getTypeClass()));
\r
569 client.setQueryParams(qp);
\r
570 client.setFragment(fragment);
\r
571 client.setPathInfo(pathinfo);
\r
572 client.setPayload(new EClient.Transfer() {
\r
574 public void transfer(OutputStream os) throws IOException, APIException {
\r
575 df.newData().out(type).direct(t,os);
\r
580 queryParams = fragment = null;
\r
581 return client.future(t);
\r
585 public<T> Future<T> delete(String pathinfo, Class<T> cls) throws APIException, CadiException {
\r
586 final int idx = pathinfo.indexOf('?');
\r
589 qp=pathinfo.substring(idx+1);
\r
590 pathinfo=pathinfo.substring(0,idx);
\r
595 EClient<CT> client = client();
\r
596 client.setMethod(DELETE);
\r
597 client.addHeader(CONTENT_TYPE, typeString(cls));
\r
598 client.setQueryParams(qp);
\r
599 client.setFragment(fragment);
\r
600 client.setPathInfo(pathinfo);
\r
601 client.setPayload(null);
\r
603 queryParams = fragment = null;
\r
604 return client.future((T)null);
\r
607 public Future<Void> delete(String pathinfo, String contentType) throws APIException, CadiException {
\r
608 final int idx = pathinfo.indexOf('?');
\r
611 qp=pathinfo.substring(idx+1);
\r
612 pathinfo=pathinfo.substring(0,idx);
\r
617 EClient<CT> client = client();
\r
618 client.setMethod(DELETE);
\r
619 client.addHeader(CONTENT_TYPE, contentType);
\r
620 client.setQueryParams(qp);
\r
621 client.setFragment(fragment);
\r
622 client.setPathInfo(pathinfo);
\r
623 client.setPayload(null);
\r
625 queryParams = fragment = null;
\r
626 return client.future(null);
\r
629 public Future<Void> transfer(final HttpServletRequest req, final HttpServletResponse resp, final String pathParam, final int expected) throws CadiException, APIException {
\r
630 EClient<CT> client = client();
\r
633 uri = new URI(req.getRequestURI());
\r
634 } catch (Exception e) {
\r
635 throw new CadiException("Invalid incoming URI",e);
\r
638 for(Enumeration<String> en = req.getHeaderNames();en.hasMoreElements();) {
\r
639 name = en.nextElement();
\r
640 client.addHeader(name,req.getHeader(name));
\r
642 client.setQueryParams(req.getQueryString());
\r
643 client.setFragment(uri.getFragment());
\r
644 client.setPathInfo(pathParam);
\r
645 String meth = req.getMethod();
\r
646 client.setMethod(meth);
\r
647 if(!"GET".equals(meth)) {
\r
648 client.setPayload(new EClient.Transfer() {
\r
650 public void transfer(OutputStream os) throws IOException, APIException {
\r
651 final ServletInputStream is = req.getInputStream();
\r
654 Pooled<byte[]> pbuff = buffPool.get();
\r
656 while((read=is.read(pbuff.content))>=0) {
\r
657 os.write(pbuff.content,0,read);
\r
666 return client.future(resp, expected);
\r
669 public String toString() {
\r
670 return uri.toString();
\r
674 * @param queryParams the queryParams to set
\r
677 public Rcli<CT> setQueryParams(String queryParams) {
\r
678 this.queryParams = queryParams;
\r
684 * @param fragment the fragment to set
\r
687 public Rcli<CT> setFragment(String fragment) {
\r
688 this.fragment = fragment;
\r
692 public URI getURI() {
\r