[AAF-21] Initial code import
[aaf/cadi.git] / client / src / main / java / com / att / cadi / client / Rcli.java
1 /*******************************************************************************\r
2  * ============LICENSE_START====================================================\r
3  * * org.onap.aai\r
4  * * ===========================================================================\r
5  * * Copyright © 2017 AT&T Intellectual Property. All rights reserved.\r
6  * * Copyright © 2017 Amdocs\r
7  * * ===========================================================================\r
8  * * Licensed under the Apache License, Version 2.0 (the "License");\r
9  * * you may not use this file except in compliance with the License.\r
10  * * You may obtain a copy of the License at\r
11  * * \r
12  *  *      http://www.apache.org/licenses/LICENSE-2.0\r
13  * * \r
14  *  * Unless required by applicable law or agreed to in writing, software\r
15  * * distributed under the License is distributed on an "AS IS" BASIS,\r
16  * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
17  * * See the License for the specific language governing permissions and\r
18  * * limitations under the License.\r
19  * * ============LICENSE_END====================================================\r
20  * *\r
21  * * ECOMP is a trademark and service mark of AT&T Intellectual Property.\r
22  * *\r
23  ******************************************************************************/\r
24 package com.att.cadi.client;\r
25 \r
26 import java.io.IOException;\r
27 import java.io.OutputStream;\r
28 import java.net.URI;\r
29 import java.util.Enumeration;\r
30 \r
31 import javax.servlet.ServletInputStream;\r
32 import javax.servlet.http.HttpServletRequest;\r
33 import javax.servlet.http.HttpServletResponse;\r
34 \r
35 import com.att.cadi.CadiException;\r
36 import com.att.cadi.SecuritySetter;\r
37 import com.att.inno.env.APIException;\r
38 import com.att.inno.env.Data.TYPE;\r
39 import com.att.inno.env.util.Pool;\r
40 import com.att.inno.env.util.Pool.Pooled;\r
41 import com.att.rosetta.env.RosettaDF;\r
42 \r
43 public abstract class Rcli<CT> {\r
44         public static final String BLANK = "";\r
45         public static final String CONTENT_TYPE = "Content-Type";\r
46         public static final String ACCEPT = "Accept";\r
47 \r
48         protected static final String POST = "POST";\r
49         protected static final String GET = "GET";\r
50         protected static final String PUT = "PUT";\r
51         protected static final String DELETE = "DELETE";\r
52         protected TYPE type;\r
53         protected String apiVersion;\r
54         protected int readTimeout = 5000;\r
55         protected int connectionTimeout = 3000;\r
56         protected URI uri;\r
57         private String queryParams, fragment;\r
58         public static Pool<byte[]> buffPool = new Pool<byte[]>(new Pool.Creator<byte[]>() {\r
59                 @Override\r
60                 public byte[] create() throws APIException {\r
61                         return new byte[1024];\r
62                 }\r
63 \r
64                 @Override\r
65                 public void destroy(byte[] t) {\r
66                 }\r
67 \r
68                 @Override\r
69                 public boolean isValid(byte[] t) {\r
70                         return true;\r
71                 }\r
72 \r
73                 @Override\r
74                 public void reuse(byte[] t) {\r
75                 }\r
76         });\r
77 \r
78 \r
79         public Rcli() {\r
80                 super();\r
81         }\r
82 \r
83         public abstract void setSecuritySetter(SecuritySetter<CT> ss);\r
84         public abstract SecuritySetter<CT> getSecuritySetter();\r
85 \r
86 \r
87         public Rcli<CT> forUser(SecuritySetter<CT> ss) {\r
88                 Rcli<CT> rv = clone(uri==null?this.uri:uri,ss);\r
89                 setSecuritySetter(ss);\r
90                 rv.type = type;\r
91                 rv.apiVersion = apiVersion;\r
92                 return rv;\r
93         }\r
94         \r
95         protected abstract Rcli<CT> clone(URI uri, SecuritySetter<CT> ss);\r
96         \r
97         public abstract void invalidate() throws CadiException;\r
98 \r
99         public Rcli<CT> readTimeout(int millis) {\r
100                 readTimeout = millis;\r
101                 return this;\r
102         }\r
103 \r
104         public Rcli<CT> connectionTimeout(int millis) {\r
105                 connectionTimeout = millis;\r
106                 return this;\r
107         }\r
108 \r
109         public Rcli<CT> type(TYPE type) {\r
110                 this.type=type;\r
111                 return this;\r
112         }\r
113 \r
114         public Rcli<CT> apiVersion(String apiVersion) {\r
115                 this.apiVersion = apiVersion;\r
116                 return this;\r
117         }\r
118         \r
119         public boolean isApiVersion(String prospective) {\r
120                 return apiVersion.equals(prospective);\r
121         }\r
122 \r
123 \r
124         public String typeString(Class<?> cls) {\r
125                 return "application/"+cls.getSimpleName()+"+"+type.name().toLowerCase()+\r
126                                 (apiVersion==null?BLANK:";version="+apiVersion);\r
127         }\r
128 \r
129         protected abstract EClient<CT> client() throws CadiException;\r
130 \r
131 \r
132         public<T> Future<T> create(String pathinfo, String contentType, final RosettaDF<T> df, final T t) throws APIException, CadiException {\r
133                 final int idx = pathinfo.indexOf('?');\r
134                 final String qp; \r
135                 if(idx>=0) {\r
136                         qp=pathinfo.substring(idx+1);\r
137                         pathinfo=pathinfo.substring(0,idx);\r
138                 } else {\r
139                         qp=queryParams;\r
140                 }\r
141                 EClient<CT> client = client();\r
142                 client.setMethod(POST);\r
143                 client.addHeader(CONTENT_TYPE,contentType);\r
144                 client.setPathInfo(pathinfo);\r
145                 client.setQueryParams(qp);\r
146                 client.setFragment(fragment);\r
147                 client.setPayload(new EClient.Transfer() {\r
148                         @Override\r
149                         public void transfer(OutputStream os) throws IOException, APIException {\r
150                                 df.newData().out(type).direct(t,os);\r
151                         }\r
152                 });\r
153                 client.send();\r
154                 queryParams = fragment = null;\r
155                 return client.futureCreate(df.getTypeClass());\r
156         }\r
157 \r
158         public<T> Future<T> create(String pathinfo, final RosettaDF<T> df, final T t) throws APIException, CadiException {\r
159                 final int idx = pathinfo.indexOf('?');\r
160                 final String qp; \r
161                 if(idx>=0) {\r
162                         qp=pathinfo.substring(idx+1);\r
163                         pathinfo=pathinfo.substring(0,idx);\r
164                 } else {\r
165                         qp=queryParams;\r
166                 }\r
167                 EClient<CT> client = client();\r
168                 client.setMethod(POST);\r
169                 client.addHeader(CONTENT_TYPE,typeString(df.getTypeClass()));\r
170                 client.setPathInfo(pathinfo);\r
171                 client.setQueryParams(qp);\r
172                 client.setFragment(fragment);\r
173                 client.setPayload(new EClient.Transfer() {\r
174                         @Override\r
175                         public void transfer(OutputStream os) throws IOException, APIException {\r
176                                 df.newData().out(type).direct(t,os);\r
177                         }\r
178                 });\r
179                 client.send();\r
180                 queryParams = fragment = null;\r
181                 return client.futureCreate(df.getTypeClass());\r
182         }\r
183 \r
184         public<T> Future<T> create(String pathinfo, Class<?> cls, final RosettaDF<T> df, final T t) throws APIException, CadiException {\r
185                 final int idx = pathinfo.indexOf('?');\r
186                 final String qp; \r
187                 if(idx>=0) {\r
188                         qp=pathinfo.substring(idx+1);\r
189                         pathinfo=pathinfo.substring(0,idx);\r
190                 } else {\r
191                         qp=queryParams;\r
192                 }\r
193 \r
194                 EClient<CT> client = client();\r
195                 client.setMethod(POST);\r
196                 client.addHeader(CONTENT_TYPE,typeString(cls));\r
197                 client.setPathInfo(pathinfo);\r
198                 client.setQueryParams(qp);\r
199                 client.setFragment(fragment);\r
200                 client.setPayload(new EClient.Transfer() {\r
201                         @Override\r
202                         public void transfer(OutputStream os) throws IOException, APIException {\r
203                                 df.newData().out(type).direct(t,os);\r
204                         }\r
205                 });\r
206                 client.send();\r
207                 queryParams = fragment = null;\r
208                 return client.futureCreate(df.getTypeClass());\r
209         }\r
210 \r
211         public<T> Future<T> create(String pathinfo, Class<T> cls) throws APIException, CadiException {\r
212                 final int idx = pathinfo.indexOf('?');\r
213                 final String qp; \r
214                 if(idx>=0) {\r
215                         qp=pathinfo.substring(idx+1);\r
216                         pathinfo=pathinfo.substring(0,idx);\r
217                 } else {\r
218                         qp=queryParams;\r
219                 }\r
220 \r
221                 EClient<CT> client = client();\r
222                 client.setMethod(POST);\r
223                 client.addHeader(CONTENT_TYPE,typeString(cls));\r
224                 client.setPathInfo(pathinfo);\r
225                 client.setQueryParams(qp);\r
226                 client.setFragment(fragment);\r
227                 client.setPayload(null);\r
228                 client.send();\r
229                 queryParams = fragment = null;\r
230                 return client.futureCreate(cls);\r
231         }\r
232 \r
233         public Future<Void> create(String pathinfo, String contentType) throws APIException, CadiException {\r
234                 final int idx = pathinfo.indexOf('?');\r
235                 final String qp; \r
236                 if(idx>=0) {\r
237                         qp=pathinfo.substring(idx+1);\r
238                         pathinfo=pathinfo.substring(0,idx);\r
239                 } else {\r
240                         qp=queryParams;\r
241                 }\r
242 \r
243                 EClient<CT> client = client();\r
244                 client.setMethod(POST);\r
245                 client.addHeader(CONTENT_TYPE,contentType);\r
246                 client.setPathInfo(pathinfo);\r
247                 client.setQueryParams(qp);\r
248                 client.setFragment(fragment);\r
249                 client.setPayload(null);\r
250                 client.send();\r
251                 queryParams = fragment = null;\r
252                 return client.futureCreate(Void.class);\r
253         }\r
254 \r
255 \r
256         public Future<String> read(String pathinfo, String accept, String ... headers) throws APIException, CadiException {\r
257                 final int idx = pathinfo.indexOf('?');\r
258                 final String qp; \r
259                 if(idx>=0) {\r
260                         qp=pathinfo.substring(idx+1);\r
261                         pathinfo=pathinfo.substring(0,idx);\r
262                 } else {\r
263                         qp=queryParams;\r
264                 }\r
265 \r
266                 EClient<CT> client = client();\r
267                 client.setMethod(GET);\r
268                 client.addHeader(ACCEPT, accept);\r
269                 \r
270                 for(int i=1;i<headers.length;i=i+2) {\r
271                         client.addHeader(headers[i-1],headers[i]);\r
272                 }\r
273                 client.setQueryParams(qp);\r
274                 client.setFragment(fragment);\r
275 \r
276                 client.setPathInfo(pathinfo);\r
277                 \r
278                 client.setPayload(null);\r
279                 client.send();\r
280                 queryParams = fragment = null;\r
281                 return client.futureReadString();\r
282         }\r
283 \r
284         public<T> Future<T> read(String pathinfo, String accept, RosettaDF<T> df, String ... headers) throws APIException, CadiException {\r
285                 final int idx = pathinfo.indexOf('?');\r
286                 final String qp; \r
287                 if(idx>=0) {\r
288                         qp=pathinfo.substring(idx+1);\r
289                         pathinfo=pathinfo.substring(0,idx);\r
290                 } else {\r
291                         qp=queryParams;\r
292                 }\r
293 \r
294                 EClient<CT> client = client();\r
295                 client.setMethod(GET);\r
296                 client.addHeader(ACCEPT, accept);\r
297                 for(int i=1;i<headers.length;i=i+2) {\r
298                         client.addHeader(headers[i-1],headers[i]);\r
299                 }\r
300                 client.setQueryParams(qp);\r
301                 client.setFragment(fragment);\r
302                 client.setPathInfo(pathinfo);\r
303                 \r
304                 client.setPayload(null);\r
305                 client.send();\r
306                 queryParams = fragment = null;\r
307                 return client.futureRead(df,type);\r
308         }\r
309 \r
310         public<T> Future<T> read(String pathinfo, RosettaDF<T> df,String ... headers) throws APIException, CadiException {\r
311                 final int idx = pathinfo.indexOf('?');\r
312                 final String qp; \r
313                 if(idx>=0) {\r
314                         qp=pathinfo.substring(idx+1);\r
315                         pathinfo=pathinfo.substring(0,idx);\r
316                 } else {\r
317                         qp=queryParams;\r
318                 }\r
319 \r
320                 EClient<CT> client = client();\r
321                 client.setMethod(GET);\r
322                 client.addHeader(ACCEPT, typeString(df.getTypeClass()));\r
323                 for(int i=1;i<headers.length;i=i+2) {\r
324                         client.addHeader(headers[i-1],headers[i]);\r
325                 }\r
326                 client.setQueryParams(qp);\r
327                 client.setFragment(fragment);\r
328                 client.setPathInfo(pathinfo);\r
329                 \r
330                 client.setPayload(null);\r
331                 client.send();\r
332                 queryParams = fragment = null;\r
333                 return client.futureRead(df,type);\r
334         }\r
335 \r
336         public<T> Future<T> read(String pathinfo, Class<?> cls, RosettaDF<T> df) throws APIException, CadiException {\r
337                 final int idx = pathinfo.indexOf('?');\r
338                 final String qp; \r
339                 if(idx>=0) {\r
340                         qp=pathinfo.substring(idx+1);\r
341                         pathinfo=pathinfo.substring(0,idx);\r
342                 } else {\r
343                         qp=queryParams;\r
344                 }\r
345 \r
346                 EClient<CT> client = client();\r
347                 client.setMethod(GET);\r
348                 client.addHeader(ACCEPT, typeString(cls));\r
349                 client.setQueryParams(qp);\r
350                 client.setFragment(fragment);\r
351                 client.setPathInfo(pathinfo);\r
352                 \r
353                 client.setPayload(null);\r
354                 client.send();\r
355                 queryParams = fragment = null;\r
356                 return client.futureRead(df,type);\r
357         }\r
358 \r
359         public<T> Future<T> update(String pathinfo, String contentType, final RosettaDF<T> df, final T t) throws APIException, CadiException {\r
360                 final int idx = pathinfo.indexOf('?');\r
361                 final String qp; \r
362                 if(idx>=0) {\r
363                         qp=pathinfo.substring(idx+1);\r
364                         pathinfo=pathinfo.substring(0,idx);\r
365                 } else {\r
366                         qp=queryParams;\r
367                 }\r
368 \r
369                 EClient<CT> client = client();\r
370                 client.setMethod(PUT);\r
371                 client.addHeader(CONTENT_TYPE,contentType);\r
372                 client.setQueryParams(qp);\r
373                 client.setFragment(fragment);\r
374                 client.setPathInfo(pathinfo);\r
375                 client.setPayload(new EClient.Transfer() {\r
376                         @Override\r
377                         public void transfer(OutputStream os) throws IOException, APIException {\r
378                                 df.newData().out(type).direct(t,os);\r
379                         }\r
380                 });\r
381                 client.send();\r
382                 queryParams = fragment = null;\r
383                 return client.future(t);\r
384         }\r
385         \r
386         public<T> Future<String> updateRespondString(String pathinfo, final RosettaDF<T> df, final T t) throws APIException, CadiException {\r
387                 final int idx = pathinfo.indexOf('?');\r
388                 final String qp; \r
389                 if(idx>=0) {\r
390                         qp=pathinfo.substring(idx+1);\r
391                         pathinfo=pathinfo.substring(0,idx);\r
392                 } else {\r
393                         qp=queryParams;\r
394                 }\r
395 \r
396                 EClient<CT> client = client();\r
397                 client.setMethod(PUT);\r
398                 client.addHeader(CONTENT_TYPE, typeString(df.getTypeClass()));\r
399                 client.setQueryParams(qp);\r
400                 client.setFragment(fragment);\r
401                 client.setPathInfo(pathinfo);\r
402                 client.setPayload(new EClient.Transfer() {\r
403                         @Override\r
404                         public void transfer(OutputStream os) throws IOException, APIException {\r
405                                 df.newData().out(type).direct(t,os);\r
406                         }\r
407                 });\r
408                 client.send();\r
409                 queryParams = fragment = null;\r
410                 return client.futureReadString();\r
411         }\r
412 \r
413 \r
414         public<T> Future<T> update(String pathinfo, final RosettaDF<T> df, final T t) throws APIException, CadiException {\r
415                 final int idx = pathinfo.indexOf('?');\r
416                 final String qp; \r
417                 if(idx>=0) {\r
418                         qp=pathinfo.substring(idx+1);\r
419                         pathinfo=pathinfo.substring(0,idx);\r
420                 } else {\r
421                         qp=queryParams;\r
422                 }\r
423 \r
424                 EClient<CT> client = client();\r
425                 client.setMethod(PUT);\r
426                 client.addHeader(CONTENT_TYPE, typeString(df.getTypeClass()));\r
427                 client.setQueryParams(qp);\r
428                 client.setFragment(fragment);\r
429                 client.setPathInfo(pathinfo);\r
430                 client.setPayload(new EClient.Transfer() {\r
431                         @Override\r
432                         public void transfer(OutputStream os) throws IOException, APIException {\r
433                                 df.newData().out(type).direct(t,os);\r
434                         }\r
435                 });\r
436                 client.send();\r
437                 queryParams = fragment = null;\r
438                 return client.future(t);\r
439         }\r
440         \r
441         public<T> Future<T> update(String pathinfo, Class<?> cls, final RosettaDF<T> df, final T t) throws APIException, CadiException {\r
442                 final int idx = pathinfo.indexOf('?');\r
443                 final String qp; \r
444                 if(idx>=0) {\r
445                         qp=pathinfo.substring(idx+1);\r
446                         pathinfo=pathinfo.substring(0,idx);\r
447                 } else {\r
448                         qp=queryParams;\r
449                 }\r
450 \r
451                 EClient<CT> client = client();\r
452                 client.setMethod(PUT);\r
453                 client.addHeader(CONTENT_TYPE, typeString(cls));\r
454                 client.setQueryParams(qp);\r
455                 client.setFragment(fragment);\r
456                 client.setPathInfo(pathinfo);\r
457                 client.setPayload(new EClient.Transfer() {\r
458                         @Override\r
459                         public void transfer(OutputStream os) throws IOException, APIException {\r
460                                 df.newData().out(type).direct(t,os);\r
461                         }\r
462                 });\r
463                 client.send();\r
464                 queryParams = fragment = null;\r
465                 return client.future(t);\r
466         }\r
467 \r
468         /**\r
469          * A method to update with a VOID\r
470          * @param pathinfo\r
471          * @param resp\r
472          * @param expected\r
473          * @return\r
474          * @throws APIException\r
475          * @throws CadiException\r
476          */\r
477         public<T> Future<Void> update(String pathinfo) throws APIException, CadiException {\r
478                 final int idx = pathinfo.indexOf('?');\r
479                 final String qp; \r
480                 if(idx>=0) {\r
481                         qp=pathinfo.substring(idx+1);\r
482                         pathinfo=pathinfo.substring(0,idx);\r
483                 } else {\r
484                         qp=queryParams;\r
485                 }\r
486 \r
487                 EClient<CT> client = client();\r
488                 client.setMethod(PUT);\r
489                 client.addHeader(CONTENT_TYPE, typeString(Void.class));\r
490                 client.setQueryParams(qp);\r
491                 client.setFragment(fragment);\r
492                 client.setPathInfo(pathinfo);\r
493 //              client.setPayload(new EClient.Transfer() {\r
494 //                      @Override\r
495 //                      public void transfer(OutputStream os) throws IOException, APIException {\r
496 //                      }\r
497 //              });\r
498                 client.send();\r
499                 queryParams = fragment = null;\r
500                 return client.future(null);\r
501         }\r
502 \r
503         public<T> Future<T> delete(String pathinfo, String contentType, final RosettaDF<T> df, final T t) throws APIException, CadiException {\r
504                 final int idx = pathinfo.indexOf('?');\r
505                 final String qp; \r
506                 if(idx>=0) {\r
507                         qp=pathinfo.substring(idx+1);\r
508                         pathinfo=pathinfo.substring(0,idx);\r
509                 } else {\r
510                         qp=queryParams;\r
511                 }\r
512 \r
513                 EClient<CT> client = client();\r
514                 client.setMethod(DELETE);\r
515                 client.addHeader(CONTENT_TYPE, contentType);\r
516                 client.setQueryParams(qp);\r
517                 client.setFragment(fragment);\r
518                 client.setPathInfo(pathinfo);\r
519                 client.setPayload(new EClient.Transfer() {\r
520                         @Override\r
521                         public void transfer(OutputStream os) throws IOException, APIException {\r
522                                 df.newData().out(type).direct(t,os);\r
523                         }\r
524                 });\r
525                 client.send();\r
526                 queryParams = fragment = null;\r
527                 return client.future(t);\r
528         }\r
529 \r
530         public<T> Future<T> delete(String pathinfo, Class<?> cls, final RosettaDF<T> df, final T t) throws APIException, CadiException {\r
531                 final int idx = pathinfo.indexOf('?');\r
532                 final String qp; \r
533                 if(idx>=0) {\r
534                         qp=pathinfo.substring(idx+1);\r
535                         pathinfo=pathinfo.substring(0,idx);\r
536                 } else {\r
537                         qp=queryParams;\r
538                 }\r
539 \r
540                 EClient<CT> client = client();\r
541                 client.setMethod(DELETE);\r
542                 client.addHeader(CONTENT_TYPE, typeString(cls));\r
543                 client.setQueryParams(qp);\r
544                 client.setFragment(fragment);\r
545                 client.setPathInfo(pathinfo);\r
546                 client.setPayload(new EClient.Transfer() {\r
547                         @Override\r
548                         public void transfer(OutputStream os) throws IOException, APIException {\r
549                                 df.newData().out(type).direct(t,os);\r
550                         }\r
551                 });\r
552                 client.send();\r
553                 queryParams = fragment = null;\r
554                 return client.future(t);\r
555         }\r
556 \r
557         public<T> Future<T> delete(String pathinfo, final RosettaDF<T> df, final T t) throws APIException, CadiException {\r
558                 final int idx = pathinfo.indexOf('?');\r
559                 final String qp; \r
560                 if(idx>=0) {\r
561                         qp=pathinfo.substring(idx+1);\r
562                         pathinfo=pathinfo.substring(0,idx);\r
563                 } else {\r
564                         qp=queryParams;\r
565                 }\r
566 \r
567                 EClient<CT> client = client();\r
568                 client.setMethod(DELETE);\r
569                 client.addHeader(CONTENT_TYPE, typeString(df.getTypeClass()));\r
570                 client.setQueryParams(qp);\r
571                 client.setFragment(fragment);\r
572                 client.setPathInfo(pathinfo);\r
573                 client.setPayload(new EClient.Transfer() {\r
574                         @Override\r
575                         public void transfer(OutputStream os) throws IOException, APIException {\r
576                                 df.newData().out(type).direct(t,os);\r
577                         }\r
578                 });\r
579 \r
580                 client.send();\r
581                 queryParams = fragment = null;\r
582                 return client.future(t);\r
583         }\r
584 \r
585 \r
586         public<T> Future<T> delete(String pathinfo, Class<T> cls) throws APIException, CadiException {\r
587                 final int idx = pathinfo.indexOf('?');\r
588                 final String qp; \r
589                 if(idx>=0) {\r
590                         qp=pathinfo.substring(idx+1);\r
591                         pathinfo=pathinfo.substring(0,idx);\r
592                 } else {\r
593                         qp=queryParams;\r
594                 }\r
595 \r
596                 EClient<CT> client = client();\r
597                 client.setMethod(DELETE);\r
598                 client.addHeader(CONTENT_TYPE, typeString(cls));\r
599                 client.setQueryParams(qp);\r
600                 client.setFragment(fragment);\r
601                 client.setPathInfo(pathinfo);\r
602                 client.setPayload(null);\r
603                 client.send();\r
604                 queryParams = fragment = null;\r
605                 return client.future((T)null);\r
606         }\r
607 \r
608         public Future<Void> delete(String pathinfo, String contentType) throws APIException, CadiException {\r
609                 final int idx = pathinfo.indexOf('?');\r
610                 final String qp; \r
611                 if(idx>=0) {\r
612                         qp=pathinfo.substring(idx+1);\r
613                         pathinfo=pathinfo.substring(0,idx);\r
614                 } else {\r
615                         qp=queryParams;\r
616                 }\r
617 \r
618                 EClient<CT> client = client();\r
619                 client.setMethod(DELETE);\r
620                 client.addHeader(CONTENT_TYPE, contentType);\r
621                 client.setQueryParams(qp);\r
622                 client.setFragment(fragment);\r
623                 client.setPathInfo(pathinfo);\r
624                 client.setPayload(null);\r
625                 client.send();\r
626                 queryParams = fragment = null;\r
627                 return client.future(null);\r
628         }\r
629 \r
630         public Future<Void> transfer(final HttpServletRequest req, final HttpServletResponse resp, final String pathParam, final int expected) throws CadiException, APIException {\r
631                 EClient<CT> client = client();\r
632                 URI uri;\r
633                 try {\r
634                         uri = new URI(req.getRequestURI());\r
635                 } catch (Exception e) {\r
636                         throw new CadiException("Invalid incoming URI",e);\r
637                 }\r
638                 String name;\r
639                 for(Enumeration<String> en = req.getHeaderNames();en.hasMoreElements();) {\r
640                         name = en.nextElement();\r
641                         client.addHeader(name,req.getHeader(name));\r
642                 }\r
643                 client.setQueryParams(req.getQueryString());\r
644                 client.setFragment(uri.getFragment());\r
645                 client.setPathInfo(pathParam);\r
646                 String meth = req.getMethod();\r
647                 client.setMethod(meth);\r
648                 if(!"GET".equals(meth)) {\r
649                         client.setPayload(new EClient.Transfer() {\r
650                                 @Override\r
651                                 public void transfer(OutputStream os) throws IOException, APIException {\r
652                                         final ServletInputStream is = req.getInputStream();\r
653                                         int read;\r
654                                         // reuse Buffers\r
655                                         Pooled<byte[]> pbuff = buffPool.get();\r
656                                         try { \r
657                                                 while((read=is.read(pbuff.content))>=0) {\r
658                                                         os.write(pbuff.content,0,read);\r
659                                                 }\r
660                                         } finally {\r
661                                                 pbuff.done();\r
662                                         }\r
663                                 }\r
664                         });\r
665                 }\r
666                 client.send();\r
667                 return client.future(resp, expected);\r
668         }\r
669 \r
670         public String toString() {\r
671                 return uri.toString();\r
672         }\r
673 \r
674         /**\r
675          * @param queryParams the queryParams to set\r
676          * @return \r
677          */\r
678         public Rcli<CT> setQueryParams(String queryParams) {\r
679                 this.queryParams = queryParams;\r
680                 return this;\r
681         }\r
682         \r
683 \r
684         /**\r
685          * @param fragment the fragment to set\r
686          * @return \r
687          */\r
688         public Rcli<CT> setFragment(String fragment) {\r
689                 this.fragment = fragment;\r
690                 return this;\r
691         }\r
692 \r
693         public URI getURI() {\r
694                 return uri;\r
695         }\r
696 \r
697 }\r