import org.onap.aaf.misc.rosetta.env.RosettaDF;
public abstract class Rcli<CT> {
- public static final String FORM_ENCODED = "application/x-www-form-urlencoded";
- public static final String APPL_JSON = "application/json";
- public static final String APPL_XML = "application/xml";
- public static final String BLANK = "";
- public static final String CONTENT_TYPE = "Content-Type";
- public static final String ACCEPT = "Accept";
-
- protected static final String POST = "POST";
- protected static final String GET = "GET";
- protected static final String PUT = "PUT";
- protected static final String DELETE = "DELETE";
- protected TYPE type;
- protected String apiVersion;
- protected int readTimeout = 5000;
- protected int connectionTimeout = 3000;
- protected URI uri;
- private String oneCallQueryParams;
- public static Pool<byte[]> buffPool = new Pool<byte[]>(new Pool.Creator<byte[]>() {
- @Override
- public byte[] create() throws APIException {
- return new byte[1024];
- }
-
- @Override
- public void destroy(byte[] t) {
- }
-
- @Override
- public boolean isValid(byte[] t) {
- return true;
- }
-
- @Override
- public void reuse(byte[] t) {
- }
- });
-
-
- public Rcli() {
- super();
- }
-
- public abstract void setSecuritySetter(SecuritySetter<CT> ss);
- public abstract SecuritySetter<CT> getSecuritySetter();
-
-
- public Rcli<CT> forUser(SecuritySetter<CT> ss) {
- Rcli<CT> rv = clone(uri==null?this.uri:uri,ss);
- setSecuritySetter(ss);
- rv.type = type;
- rv.apiVersion = apiVersion;
- return rv;
- }
-
- protected abstract Rcli<CT> clone(URI uri, SecuritySetter<CT> ss);
-
- public abstract void invalidate() throws CadiException;
-
- public Rcli<CT> readTimeout(int millis) {
- readTimeout = millis;
- return this;
- }
-
- public Rcli<CT> connectionTimeout(int millis) {
- connectionTimeout = millis;
- return this;
- }
-
- public Rcli<CT> type(TYPE type) {
- this.type=type;
- return this;
- }
-
- public Rcli<CT> apiVersion(String apiVersion) {
- this.apiVersion = apiVersion;
- return this;
- }
-
- public boolean isApiVersion(String prospective) {
- return apiVersion.equals(prospective);
- }
-
-
- public String typeString(Class<?> cls) {
- return "application/"+cls.getSimpleName()+"+"+type.name().toLowerCase()+
- (apiVersion==null?BLANK:";version="+apiVersion);
- }
-
- protected abstract EClient<CT> client() throws CadiException;
-
-
- public<T> Future<T> create(final String pathinfo, final String contentType, final RosettaDF<T> df, final T t) throws APIException, CadiException {
- final ParsePath pp = new ParsePath(pathinfo);
-
- EClient<CT> client = client();
- client.setMethod(POST);
- client.addHeader(CONTENT_TYPE,contentType);
- client.setPathInfo(pp.path());
- client.setQueryParams(pp.query());
- client.setFragment(pp.frag());
- client.setPayload(new EClient.Transfer() {
- @Override
- public void transfer(OutputStream os) throws IOException, APIException {
- df.newData().out(type).direct(t,os);
- }
- });
- client.send();
- return client.futureCreate(df.getTypeClass());
- }
-
- public<T> Future<T> create(String pathinfo, final RosettaDF<T> df, final T t) throws APIException, CadiException {
- final ParsePath pp = new ParsePath(pathinfo);
-
- EClient<CT> client = client();
- client.setMethod(POST);
- client.addHeader(CONTENT_TYPE,typeString(df.getTypeClass()));
- client.setPathInfo(pp.path());
- client.setQueryParams(pp.query());
- client.setFragment(pp.frag());
- client.setPayload(new EClient.Transfer() {
- @Override
- public void transfer(OutputStream os) throws IOException, APIException {
- df.newData().out(type).direct(t,os);
- }
- });
- client.send();
- return client.futureCreate(df.getTypeClass());
- }
-
- public<T> Future<T> create(String pathinfo, Class<?> cls, final RosettaDF<T> df, final T t) throws APIException, CadiException {
- final ParsePath pp = new ParsePath(pathinfo);
-
- EClient<CT> client = client();
- client.setMethod(POST);
- client.addHeader(CONTENT_TYPE,typeString(cls));
- client.setPathInfo(pp.path());
- client.setQueryParams(pp.query());
- client.setFragment(pp.frag());
- client.setPayload(new EClient.Transfer() {
- @Override
- public void transfer(OutputStream os) throws IOException, APIException {
- df.newData().out(type).direct(t,os);
- }
- });
- client.send();
- return client.futureCreate(df.getTypeClass());
- }
-
- public<T> Future<T> create(String pathinfo, Class<T> cls) throws APIException, CadiException {
- final ParsePath pp = new ParsePath(pathinfo);
-
- EClient<CT> client = client();
- client.setMethod(POST);
- client.addHeader(CONTENT_TYPE,typeString(cls));
- client.setPathInfo(pp.path());
- client.setQueryParams(pp.query());
- client.setFragment(pp.frag());
- client.setPayload(null);
- client.send();
- return client.futureCreate(cls);
- }
-
- public Future<Void> create(String pathinfo, String contentType) throws APIException, CadiException {
- final ParsePath pp = new ParsePath(pathinfo);
-
- EClient<CT> client = client();
- client.setMethod(POST);
- client.addHeader(CONTENT_TYPE,contentType);
- client.setPathInfo(pp.path());
- client.setQueryParams(pp.query());
- client.setFragment(pp.frag());
- client.setPayload(null);
- client.send();
- return client.futureCreate(Void.class);
- }
-
- public Future<Void> create(String pathinfo, String contentType, EClient.Transfer content) throws APIException, CadiException {
- final ParsePath pp = new ParsePath(pathinfo);
-
- EClient<CT> client = client();
- client.setMethod(POST);
- client.addHeader(CONTENT_TYPE,contentType);
- client.setPathInfo(pp.path());
- client.setQueryParams(pp.query());
- client.setFragment(pp.frag());
- client.setPayload(content);
- client.send();
- return client.futureCreate(Void.class);
- }
-
-
- /**
- * Post Data in WWW expected format, with the format tag1=value1&tag2=value2, etc
- * Note Shortcut:
- * Because typically, you will want to have a variable as value, you can type, as long as tag ends with "="
- * postForm(..., "tag1=value1","tag2=",var2);
- * @param pathinfo
- * @param df
- * @param cls
- * @param formParam
- * @return
- * @throws APIException
- * @throws CadiException
- */
- public <T> Future<T> postForm(String pathinfo, final RosettaDF<T> df, final String ... formParam) throws APIException, CadiException {
- final ParsePath pp = new ParsePath(pathinfo);
-
- EClient<CT> client = client();
- client.setMethod(POST);
- client.addHeader(CONTENT_TYPE,FORM_ENCODED);
- switch(type) {
- case JSON:
- client.addHeader(ACCEPT, APPL_JSON);
- break;
- case XML:
- client.addHeader(ACCEPT, APPL_XML);
- break;
- default:
- break;
- }
- client.setPathInfo(pp.path());
- client.setQueryParams(pp.query());
- client.setFragment(pp.frag());
- client.setPayload(new Transfer() {
- @Override
- public void transfer(OutputStream os) throws IOException, APIException {
- PrintStream ps;
- if(os instanceof PrintStream) {
- ps = (PrintStream)os;
- } else {
- ps = new PrintStream(os);
- }
- boolean first = true;
- for(String fp : formParam) {
- if(fp!=null) {
- if(first) {
- first = false;
- } else {
- ps.print('&');
- }
- if(fp.endsWith("=")) {
- first = true;
- }
- ps.print(fp);
- }
- }
- }});
- client.send();
- return client.futureRead(df,TYPE.JSON);
- }
-
- /**
- * Read String, using POST for keyInfo
- *
- * @param pathinfo
- * @param df
- * @param t
- * @param resp
- * @return
- * @throws APIException
- * @throws CadiException
- */
- public<T> Future<String> readPost(String pathinfo, final RosettaDF<T> df, final T t) throws APIException, CadiException {
- final ParsePath pp = new ParsePath(pathinfo);
-
- EClient<CT> client = client();
- client.setMethod(POST);
- client.addHeader(CONTENT_TYPE,typeString(df.getTypeClass()));
- client.setPathInfo(pp.path());
- client.setQueryParams(pp.query());
- client.setFragment(pp.frag());
- client.setPayload(new EClient.Transfer() {
- @Override
- public void transfer(OutputStream os) throws IOException, APIException {
- df.newData().out(type).direct(t,os);
- }
- });
- client.send();
- return client.futureReadString();
- }
-
- /**
- * Read using POST for keyInfo, responding with marshaled Objects
- *
- * @param pathinfo
- * @param df
- * @param t
- * @param resp
- * @return
- * @throws APIException
- * @throws CadiException
- */
- public<T,R> Future<R> readPost(String pathinfo, final RosettaDF<T> df, final T t, final RosettaDF<R> resp) throws APIException, CadiException {
- final ParsePath pp = new ParsePath(pathinfo);
-
- EClient<CT> client = client();
- client.setMethod(POST);
- client.addHeader(CONTENT_TYPE,typeString(df.getTypeClass()));
- client.setPathInfo(pp.path());
- client.setQueryParams(pp.query());
- client.setFragment(pp.frag());
- client.setPayload(new EClient.Transfer() {
- @Override
- public void transfer(OutputStream os) throws IOException, APIException {
- df.newData().out(type).direct(t,os);
- }
- });
- client.send();
- return client.futureRead(resp,resp.getOutType());
- }
-
- public Future<String> readPost(String pathinfo, String contentType, String ... headers) throws CadiException, APIException {
- final ParsePath pp = new ParsePath(pathinfo);
-
- EClient<CT> client = client();
- client.setMethod(POST);
- client.addHeader(CONTENT_TYPE,contentType);
- client.setPathInfo(pp.path());
- client.setQueryParams(pp.query());
- client.setFragment(pp.frag());
- client.setPayload(new EClient.Transfer() {
- @Override
- public void transfer(OutputStream os) throws IOException, APIException {
- }});
- client.send();
- return client.futureReadString();
- }
-
- public Future<String> read(String pathinfo, String accept, String ... headers) throws APIException, CadiException {
- final ParsePath pp = new ParsePath(pathinfo);
-
- EClient<CT> client = client();
- client.setMethod(GET);
- client.addHeader(ACCEPT, accept);
-
- for(int i=1;i<headers.length;i=i+2) {
- client.addHeader(headers[i-1],headers[i]);
- }
- client.setPathInfo(pp.path());
- client.setQueryParams(pp.query());
- client.setFragment(pp.frag());
- client.setPayload(null);
- client.send();
- return client.futureReadString();
- }
-
- public<T> Future<T> read(String pathinfo, String accept, RosettaDF<T> df, String ... headers) throws APIException, CadiException {
- final ParsePath pp = new ParsePath(pathinfo);
-
- EClient<CT> client = client();
- client.setMethod(GET);
- client.addHeader(ACCEPT, accept);
- for(int i=1;i<headers.length;i=i+2) {
- client.addHeader(headers[i-1],headers[i]);
- }
- client.setPathInfo(pp.path());
- client.setQueryParams(pp.query());
- client.setFragment(pp.frag());
- client.setPayload(null);
- client.send();
- return client.futureRead(df,type);
- }
-
- public<T> Future<T> read(String pathinfo, RosettaDF<T> df,String ... headers) throws APIException, CadiException {
- final ParsePath pp = new ParsePath(pathinfo);
-
- EClient<CT> client = client();
- client.setMethod(GET);
- client.addHeader(ACCEPT, typeString(df.getTypeClass()));
- for(int i=1;i<headers.length;i=i+2) {
- client.addHeader(headers[i-1],headers[i]);
- }
- client.setPathInfo(pp.path());
- client.setQueryParams(pp.query());
- client.setFragment(pp.frag());
-
- client.setPayload(null);
- client.send();
- return client.futureRead(df,type);
- }
-
- public<T> Future<T> read(String pathinfo, Class<?> cls, RosettaDF<T> df) throws APIException, CadiException {
- final ParsePath pp = new ParsePath(pathinfo);
-
- EClient<CT> client = client();
- client.setMethod(GET);
- client.addHeader(ACCEPT, typeString(cls));
- client.setPathInfo(pp.path());
- client.setQueryParams(pp.query());
- client.setFragment(pp.frag());
-
- client.setPayload(null);
- client.send();
- return client.futureRead(df,type);
- }
-
- public<T> Future<T> update(String pathinfo, String contentType, final RosettaDF<T> df, final T t) throws APIException, CadiException {
- final ParsePath pp = new ParsePath(pathinfo);
-
- EClient<CT> client = client();
- client.setMethod(PUT);
- client.addHeader(CONTENT_TYPE,contentType);
- client.setPathInfo(pp.path());
- client.setQueryParams(pp.query());
- client.setFragment(pp.frag());
- client.setPayload(new EClient.Transfer() {
- @Override
- public void transfer(OutputStream os) throws IOException, APIException {
- df.newData().out(type).direct(t,os);
- }
- });
- client.send();
- return client.future(t);
- }
-
- public<T> Future<String> updateRespondString(String pathinfo, final RosettaDF<T> df, final T t) throws APIException, CadiException {
- final ParsePath pp = new ParsePath(pathinfo);
-
- EClient<CT> client = client();
- client.setMethod(PUT);
- client.addHeader(CONTENT_TYPE, typeString(df.getTypeClass()));
- client.setPathInfo(pp.path());
- client.setQueryParams(pp.query());
- client.setFragment(pp.frag());
-
- client.setPayload(new EClient.Transfer() {
- @Override
- public void transfer(OutputStream os) throws IOException, APIException {
- //String s = df.newData().out(type).load(t).asString();
- df.newData().out(type).direct(t,os);
- }
- });
- client.send();
- return client.futureReadString();
- }
-
- public Future<String> update(String pathinfo, String contentType, EClient.Transfer content) throws APIException, CadiException {
- final ParsePath pp = new ParsePath(pathinfo);
-
- EClient<CT> client = client();
- client.setMethod(PUT);
- client.addHeader(CONTENT_TYPE,contentType);
- client.setPathInfo(pp.path());
- client.setQueryParams(pp.query());
- client.setFragment(pp.frag());
- client.setPayload(content);
- client.send();
- return client.futureReadString();
- }
-
-
-
-
- public<T> Future<T> update(String pathinfo, final RosettaDF<T> df, final T t) throws APIException, CadiException {
- final ParsePath pp = new ParsePath(pathinfo);
-
- EClient<CT> client = client();
- client.setMethod(PUT);
- client.addHeader(CONTENT_TYPE, typeString(df.getTypeClass()));
- client.setPathInfo(pp.path());
- client.setQueryParams(pp.query());
- client.setFragment(pp.frag());
-
- client.setPayload(new EClient.Transfer() {
- @Override
- public void transfer(OutputStream os) throws IOException, APIException {
- df.newData().out(type).direct(t,os);
- }
- });
- client.send();
- return client.future(t);
- }
-
- public<T> Future<T> update(String pathinfo, Class<?> cls, final RosettaDF<T> df, final T t) throws APIException, CadiException {
- final ParsePath pp = new ParsePath(pathinfo);
-
- EClient<CT> client = client();
- client.setMethod(PUT);
- client.addHeader(CONTENT_TYPE, typeString(cls));
- client.setPathInfo(pp.path());
- client.setQueryParams(pp.query());
- client.setFragment(pp.frag());
-
- client.setPayload(new EClient.Transfer() {
- @Override
- public void transfer(OutputStream os) throws IOException, APIException {
- df.newData().out(type).direct(t,os);
- }
- });
- client.send();
- return client.future(t);
- }
-
-
-
- /**
- * A method to update with a VOID
- * @param pathinfo
- * @param resp
- * @param expected
- * @return
- * @throws APIException
- * @throws CadiException
- */
- public<T> Future<Void> update(String pathinfo) throws APIException, CadiException {
- final ParsePath pp = new ParsePath(pathinfo);
-
- EClient<CT> client = client();
- client.setMethod(PUT);
- client.addHeader(CONTENT_TYPE, typeString(Void.class));
- client.setPathInfo(pp.path());
- client.setQueryParams(pp.query());
- client.setFragment(pp.frag());
-
-// client.setPayload(new EClient.Transfer() {
-// @Override
-// public void transfer(OutputStream os) throws IOException, APIException {
-// }
-// });
- client.send();
- return client.future(null);
- }
-
-
- public<T> Future<T> delete(String pathinfo, String contentType, final RosettaDF<T> df, final T t) throws APIException, CadiException {
- final ParsePath pp = new ParsePath(pathinfo);
-
- EClient<CT> client = client();
- client.setMethod(DELETE);
- client.addHeader(CONTENT_TYPE, contentType);
- client.setPathInfo(pp.path());
- client.setQueryParams(pp.query());
- client.setFragment(pp.frag());
-
- client.setPayload(new EClient.Transfer() {
- @Override
- public void transfer(OutputStream os) throws IOException, APIException {
- df.newData().out(type).direct(t,os);
- }
- });
- client.send();
- return client.future(t);
- }
-
- public<T> Future<T> delete(String pathinfo, Class<?> cls, final RosettaDF<T> df, final T t) throws APIException, CadiException {
- final ParsePath pp = new ParsePath(pathinfo);
-
- EClient<CT> client = client();
- client.setMethod(DELETE);
- client.addHeader(CONTENT_TYPE, typeString(cls));
- client.setPathInfo(pp.path());
- client.setQueryParams(pp.query());
- client.setFragment(pp.frag());
- client.setPayload(new EClient.Transfer() {
- @Override
- public void transfer(OutputStream os) throws IOException, APIException {
- df.newData().out(type).direct(t,os);
- }
- });
- client.send();
- return client.future(t);
- }
-
- public<T> Future<T> delete(String pathinfo, final RosettaDF<T> df, final T t) throws APIException, CadiException {
- final ParsePath pp = new ParsePath(pathinfo);
-
- EClient<CT> client = client();
- client.setMethod(DELETE);
- client.addHeader(CONTENT_TYPE, typeString(df.getTypeClass()));
- client.setPathInfo(pp.path());
- client.setQueryParams(pp.query());
- client.setFragment(pp.frag());
- client.setPayload(new EClient.Transfer() {
- @Override
- public void transfer(OutputStream os) throws IOException, APIException {
- df.newData().out(type).direct(t,os);
- }
- });
-
- client.send();
- return client.future(t);
- }
-
-
- public<T> Future<T> delete(String pathinfo, Class<T> cls) throws APIException, CadiException {
- final ParsePath pp = new ParsePath(pathinfo);
-
- EClient<CT> client = client();
- client.setMethod(DELETE);
- client.addHeader(CONTENT_TYPE, typeString(cls));
- client.setPathInfo(pp.path());
- client.setQueryParams(pp.query());
- client.setFragment(pp.frag());
-
- client.setPayload(null);
- client.send();
- return client.future((T)null);
- }
-
- public Future<Void> delete(String pathinfo, String contentType) throws APIException, CadiException {
- final ParsePath pp = new ParsePath(pathinfo);
-
- EClient<CT> client = client();
- client.setMethod(DELETE);
- client.addHeader(CONTENT_TYPE, contentType);
- client.setPathInfo(pp.path());
- client.setQueryParams(pp.query());
- client.setFragment(pp.frag());
-
- client.setPayload(null);
- client.send();
- return client.future(null);
- }
-
- public Future<Void> transfer(final HttpServletRequest req, final HttpServletResponse resp, final String pathParam, final int expected) throws CadiException, APIException {
- EClient<CT> client = client();
- URI uri;
- try {
- uri = new URI(req.getRequestURI());
- } catch (Exception e) {
- throw new CadiException("Invalid incoming URI",e);
- }
- String name;
- for(Enumeration<String> en = req.getHeaderNames();en.hasMoreElements();) {
- name = en.nextElement();
- client.addHeader(name,req.getHeader(name));
- }
- client.setQueryParams(req.getQueryString());
- client.setFragment(uri.getFragment());
- client.setPathInfo(pathParam);
- String meth = req.getMethod();
- client.setMethod(meth);
- if(!"GET".equals(meth)) {
- client.setPayload(new EClient.Transfer() {
- @Override
- public void transfer(OutputStream os) throws IOException, APIException {
- final ServletInputStream is = req.getInputStream();
- int read;
- // reuse Buffers
- Pooled<byte[]> pbuff = buffPool.get();
- try {
- while((read=is.read(pbuff.content))>=0) {
- os.write(pbuff.content,0,read);
- }
- } finally {
- pbuff.done();
- }
- }
- });
- }
- client.send();
- return client.future(resp, expected);
- }
-
- private class ParsePath {
- private final String path;
- private final int query;
- private final int queryEnd;
- private final int pound;
- private final String queryParams;
-
- public ParsePath(final String origPath) {
- path = origPath;
- if(origPath==null) {
- query=queryEnd=pound=-1;
- queryParams=null;
- } else {
- query = origPath.indexOf('?');
- pound = origPath.indexOf('#');
- queryEnd = pound>=0?pound:path.length();
- if(oneCallQueryParams==null) {
- if(query>=0) {
- queryParams = path.substring(query+1,queryEnd);
- } else {
- queryParams=null;
- }
- } else {
- if(query>=0) {
- queryParams = oneCallQueryParams + '&' + path.substring(query+1,queryEnd);
- } else {
- queryParams = oneCallQueryParams;
- }
- oneCallQueryParams = null;
- }
- }
- }
-
- public String path() {
- if(query>=0) {
- if(pound>=0) {
- return path.substring(pound+1);
- }
- return path.substring(0,query);
- } else if(pound>=0) {
- return path.substring(0,pound);
- } else {
- return path;
- }
- }
-
- public String query() {
- return queryParams;
- }
-
- public String frag() {
- if(pound>=0) {
- return path.substring(pound+1);
- } else {
- return null;
- }
- }
- }
-
- public String toString() {
- return uri.toString();
- }
-
- public URI getURI() {
- return uri;
- }
-
- public void setQueryParams(final String queryParams) {
- oneCallQueryParams=queryParams;
- }
+ public static final String FORM_ENCODED = "application/x-www-form-urlencoded";
+ public static final String APPL_JSON = "application/json";
+ public static final String APPL_XML = "application/xml";
+ public static final String BLANK = "";
+ public static final String CONTENT_TYPE = "Content-Type";
+ public static final String ACCEPT = "Accept";
+
+ protected static final String POST = "POST";
+ protected static final String GET = "GET";
+ protected static final String PUT = "PUT";
+ protected static final String DELETE = "DELETE";
+ protected TYPE type;
+ protected String apiVersion;
+ protected int readTimeout = 5000;
+ protected int connectionTimeout = 3000;
+ protected URI uri;
+ private String oneCallQueryParams;
+ public static Pool<byte[]> buffPool = new Pool<byte[]>(new Pool.Creator<byte[]>() {
+ @Override
+ public byte[] create() throws APIException {
+ return new byte[1024];
+ }
+
+ @Override
+ public void destroy(byte[] t) {
+ }
+
+ @Override
+ public boolean isValid(byte[] t) {
+ return true;
+ }
+
+ @Override
+ public void reuse(byte[] t) {
+ }
+ });
+
+
+ public Rcli() {
+ super();
+ }
+
+ public abstract void setSecuritySetter(SecuritySetter<CT> ss);
+ public abstract SecuritySetter<CT> getSecuritySetter();
+
+
+ public Rcli<CT> forUser(SecuritySetter<CT> ss) {
+ Rcli<CT> rv = clone(uri==null?this.uri:uri,ss);
+ setSecuritySetter(ss);
+ rv.type = type;
+ rv.apiVersion = apiVersion;
+ return rv;
+ }
+
+ protected abstract Rcli<CT> clone(URI uri, SecuritySetter<CT> ss);
+
+ public abstract void invalidate() throws CadiException;
+
+ public Rcli<CT> readTimeout(int millis) {
+ readTimeout = millis;
+ return this;
+ }
+
+ public Rcli<CT> connectionTimeout(int millis) {
+ connectionTimeout = millis;
+ return this;
+ }
+
+ public Rcli<CT> type(TYPE type) {
+ this.type=type;
+ return this;
+ }
+
+ public Rcli<CT> apiVersion(String apiVersion) {
+ this.apiVersion = apiVersion;
+ return this;
+ }
+
+ public boolean isApiVersion(String prospective) {
+ return apiVersion.equals(prospective);
+ }
+
+
+ public String typeString(Class<?> cls) {
+ return "application/"+cls.getSimpleName()+"+"+type.name().toLowerCase()+
+ (apiVersion==null?BLANK:";version="+apiVersion);
+ }
+
+ protected abstract EClient<CT> client() throws CadiException;
+
+
+ public<T> Future<T> create(final String pathinfo, final String contentType, final RosettaDF<T> df, final T t) throws APIException, CadiException {
+ final ParsePath pp = new ParsePath(pathinfo);
+
+ EClient<CT> client = client();
+ client.setMethod(POST);
+ client.addHeader(CONTENT_TYPE,contentType);
+ client.setPathInfo(pp.path());
+ client.setQueryParams(pp.query());
+ client.setFragment(pp.frag());
+ client.setPayload(new EClient.Transfer() {
+ @Override
+ public void transfer(OutputStream os) throws IOException, APIException {
+ df.newData().out(type).direct(t,os);
+ }
+ });
+ client.send();
+ return client.futureCreate(df.getTypeClass());
+ }
+
+ public<T> Future<T> create(String pathinfo, final RosettaDF<T> df, final T t) throws APIException, CadiException {
+ final ParsePath pp = new ParsePath(pathinfo);
+
+ EClient<CT> client = client();
+ client.setMethod(POST);
+ client.addHeader(CONTENT_TYPE,typeString(df.getTypeClass()));
+ client.setPathInfo(pp.path());
+ client.setQueryParams(pp.query());
+ client.setFragment(pp.frag());
+ client.setPayload(new EClient.Transfer() {
+ @Override
+ public void transfer(OutputStream os) throws IOException, APIException {
+ df.newData().out(type).direct(t,os);
+ }
+ });
+ client.send();
+ return client.futureCreate(df.getTypeClass());
+ }
+
+ public<T> Future<T> create(String pathinfo, Class<?> cls, final RosettaDF<T> df, final T t) throws APIException, CadiException {
+ final ParsePath pp = new ParsePath(pathinfo);
+
+ EClient<CT> client = client();
+ client.setMethod(POST);
+ client.addHeader(CONTENT_TYPE,typeString(cls));
+ client.setPathInfo(pp.path());
+ client.setQueryParams(pp.query());
+ client.setFragment(pp.frag());
+ client.setPayload(new EClient.Transfer() {
+ @Override
+ public void transfer(OutputStream os) throws IOException, APIException {
+ df.newData().out(type).direct(t,os);
+ }
+ });
+ client.send();
+ return client.futureCreate(df.getTypeClass());
+ }
+
+ public<T> Future<T> create(String pathinfo, Class<T> cls) throws APIException, CadiException {
+ final ParsePath pp = new ParsePath(pathinfo);
+
+ EClient<CT> client = client();
+ client.setMethod(POST);
+ client.addHeader(CONTENT_TYPE,typeString(cls));
+ client.setPathInfo(pp.path());
+ client.setQueryParams(pp.query());
+ client.setFragment(pp.frag());
+ client.setPayload(null);
+ client.send();
+ return client.futureCreate(cls);
+ }
+
+ public Future<Void> create(String pathinfo, String contentType) throws APIException, CadiException {
+ final ParsePath pp = new ParsePath(pathinfo);
+
+ EClient<CT> client = client();
+ client.setMethod(POST);
+ client.addHeader(CONTENT_TYPE,contentType);
+ client.setPathInfo(pp.path());
+ client.setQueryParams(pp.query());
+ client.setFragment(pp.frag());
+ client.setPayload(null);
+ client.send();
+ return client.futureCreate(Void.class);
+ }
+
+ public Future<Void> create(String pathinfo, String contentType, EClient.Transfer content) throws APIException, CadiException {
+ final ParsePath pp = new ParsePath(pathinfo);
+
+ EClient<CT> client = client();
+ client.setMethod(POST);
+ client.addHeader(CONTENT_TYPE,contentType);
+ client.setPathInfo(pp.path());
+ client.setQueryParams(pp.query());
+ client.setFragment(pp.frag());
+ client.setPayload(content);
+ client.send();
+ return client.futureCreate(Void.class);
+ }
+
+
+ /**
+ * Post Data in WWW expected format, with the format tag1=value1&tag2=value2, etc
+ * Note Shortcut:
+ * Because typically, you will want to have a variable as value, you can type, as long as tag ends with "="
+ * postForm(..., "tag1=value1","tag2=",var2);
+ * @param pathinfo
+ * @param df
+ * @param cls
+ * @param formParam
+ * @return
+ * @throws APIException
+ * @throws CadiException
+ */
+ public <T> Future<T> postForm(String pathinfo, final RosettaDF<T> df, final String ... formParam) throws APIException, CadiException {
+ final ParsePath pp = new ParsePath(pathinfo);
+
+ EClient<CT> client = client();
+ client.setMethod(POST);
+ client.addHeader(CONTENT_TYPE,FORM_ENCODED);
+ switch(type) {
+ case JSON:
+ client.addHeader(ACCEPT, APPL_JSON);
+ break;
+ case XML:
+ client.addHeader(ACCEPT, APPL_XML);
+ break;
+ default:
+ break;
+ }
+ client.setPathInfo(pp.path());
+ client.setQueryParams(pp.query());
+ client.setFragment(pp.frag());
+ client.setPayload(new Transfer() {
+ @Override
+ public void transfer(OutputStream os) throws IOException, APIException {
+ PrintStream ps;
+ if (os instanceof PrintStream) {
+ ps = (PrintStream)os;
+ } else {
+ ps = new PrintStream(os);
+ }
+ boolean first = true;
+ for (String fp : formParam) {
+ if (fp!=null) {
+ if (first) {
+ first = false;
+ } else {
+ ps.print('&');
+ }
+ if (fp.endsWith("=")) {
+ first = true;
+ }
+ ps.print(fp);
+ }
+ }
+ }});
+ client.send();
+ return client.futureRead(df,TYPE.JSON);
+ }
+
+ /**
+ * Read String, using POST for keyInfo
+ *
+ * @param pathinfo
+ * @param df
+ * @param t
+ * @param resp
+ * @return
+ * @throws APIException
+ * @throws CadiException
+ */
+ public<T> Future<String> readPost(String pathinfo, final RosettaDF<T> df, final T t) throws APIException, CadiException {
+ final ParsePath pp = new ParsePath(pathinfo);
+
+ EClient<CT> client = client();
+ client.setMethod(POST);
+ client.addHeader(CONTENT_TYPE,typeString(df.getTypeClass()));
+ client.setPathInfo(pp.path());
+ client.setQueryParams(pp.query());
+ client.setFragment(pp.frag());
+ client.setPayload(new EClient.Transfer() {
+ @Override
+ public void transfer(OutputStream os) throws IOException, APIException {
+ df.newData().out(type).direct(t,os);
+ }
+ });
+ client.send();
+ return client.futureReadString();
+ }
+
+ /**
+ * Read using POST for keyInfo, responding with marshaled Objects
+ *
+ * @param pathinfo
+ * @param df
+ * @param t
+ * @param resp
+ * @return
+ * @throws APIException
+ * @throws CadiException
+ */
+ public<T,R> Future<R> readPost(String pathinfo, final RosettaDF<T> df, final T t, final RosettaDF<R> resp) throws APIException, CadiException {
+ final ParsePath pp = new ParsePath(pathinfo);
+
+ EClient<CT> client = client();
+ client.setMethod(POST);
+ client.addHeader(CONTENT_TYPE,typeString(df.getTypeClass()));
+ client.setPathInfo(pp.path());
+ client.setQueryParams(pp.query());
+ client.setFragment(pp.frag());
+ client.setPayload(new EClient.Transfer() {
+ @Override
+ public void transfer(OutputStream os) throws IOException, APIException {
+ df.newData().out(type).direct(t,os);
+ }
+ });
+ client.send();
+ return client.futureRead(resp,resp.getOutType());
+ }
+
+ public Future<String> readPost(String pathinfo, String contentType, String ... headers) throws CadiException, APIException {
+ final ParsePath pp = new ParsePath(pathinfo);
+
+ EClient<CT> client = client();
+ client.setMethod(POST);
+ client.addHeader(CONTENT_TYPE,contentType);
+ client.setPathInfo(pp.path());
+ client.setQueryParams(pp.query());
+ client.setFragment(pp.frag());
+ client.setPayload(new EClient.Transfer() {
+ @Override
+ public void transfer(OutputStream os) throws IOException, APIException {
+ }});
+ client.send();
+ return client.futureReadString();
+ }
+
+ public Future<String> read(String pathinfo, String accept, String ... headers) throws APIException, CadiException {
+ final ParsePath pp = new ParsePath(pathinfo);
+
+ EClient<CT> client = client();
+ client.setMethod(GET);
+ client.addHeader(ACCEPT, accept);
+
+ for (int i=1;i<headers.length;i=i+2) {
+ client.addHeader(headers[i-1],headers[i]);
+ }
+ client.setPathInfo(pp.path());
+ client.setQueryParams(pp.query());
+ client.setFragment(pp.frag());
+ client.setPayload(null);
+ client.send();
+ return client.futureReadString();
+ }
+
+ public<T> Future<T> read(String pathinfo, String accept, RosettaDF<T> df, String ... headers) throws APIException, CadiException {
+ final ParsePath pp = new ParsePath(pathinfo);
+
+ EClient<CT> client = client();
+ client.setMethod(GET);
+ client.addHeader(ACCEPT, accept);
+ for (int i=1;i<headers.length;i=i+2) {
+ client.addHeader(headers[i-1],headers[i]);
+ }
+ client.setPathInfo(pp.path());
+ client.setQueryParams(pp.query());
+ client.setFragment(pp.frag());
+ client.setPayload(null);
+ client.send();
+ return client.futureRead(df,type);
+ }
+
+ public<T> Future<T> read(String pathinfo, RosettaDF<T> df,String ... headers) throws APIException, CadiException {
+ final ParsePath pp = new ParsePath(pathinfo);
+
+ EClient<CT> client = client();
+ client.setMethod(GET);
+ client.addHeader(ACCEPT, typeString(df.getTypeClass()));
+ for (int i=1;i<headers.length;i=i+2) {
+ client.addHeader(headers[i-1],headers[i]);
+ }
+ client.setPathInfo(pp.path());
+ client.setQueryParams(pp.query());
+ client.setFragment(pp.frag());
+
+ client.setPayload(null);
+ client.send();
+ return client.futureRead(df,type);
+ }
+
+ public<T> Future<T> read(String pathinfo, Class<?> cls, RosettaDF<T> df) throws APIException, CadiException {
+ final ParsePath pp = new ParsePath(pathinfo);
+
+ EClient<CT> client = client();
+ client.setMethod(GET);
+ client.addHeader(ACCEPT, typeString(cls));
+ client.setPathInfo(pp.path());
+ client.setQueryParams(pp.query());
+ client.setFragment(pp.frag());
+
+ client.setPayload(null);
+ client.send();
+ return client.futureRead(df,type);
+ }
+
+ public<T> Future<T> update(String pathinfo, String contentType, final RosettaDF<T> df, final T t) throws APIException, CadiException {
+ final ParsePath pp = new ParsePath(pathinfo);
+
+ EClient<CT> client = client();
+ client.setMethod(PUT);
+ client.addHeader(CONTENT_TYPE,contentType);
+ client.setPathInfo(pp.path());
+ client.setQueryParams(pp.query());
+ client.setFragment(pp.frag());
+ client.setPayload(new EClient.Transfer() {
+ @Override
+ public void transfer(OutputStream os) throws IOException, APIException {
+ df.newData().out(type).direct(t,os);
+ }
+ });
+ client.send();
+ return client.future(t);
+ }
+
+ public<T> Future<String> updateRespondString(String pathinfo, final RosettaDF<T> df, final T t) throws APIException, CadiException {
+ final ParsePath pp = new ParsePath(pathinfo);
+
+ EClient<CT> client = client();
+ client.setMethod(PUT);
+ client.addHeader(CONTENT_TYPE, typeString(df.getTypeClass()));
+ client.setPathInfo(pp.path());
+ client.setQueryParams(pp.query());
+ client.setFragment(pp.frag());
+
+ client.setPayload(new EClient.Transfer() {
+ @Override
+ public void transfer(OutputStream os) throws IOException, APIException {
+ //String s = df.newData().out(type).load(t).asString();
+ df.newData().out(type).direct(t,os);
+ }
+ });
+ client.send();
+ return client.futureReadString();
+ }
+
+ public Future<String> update(String pathinfo, String contentType, EClient.Transfer content) throws APIException, CadiException {
+ final ParsePath pp = new ParsePath(pathinfo);
+
+ EClient<CT> client = client();
+ client.setMethod(PUT);
+ client.addHeader(CONTENT_TYPE,contentType);
+ client.setPathInfo(pp.path());
+ client.setQueryParams(pp.query());
+ client.setFragment(pp.frag());
+ client.setPayload(content);
+ client.send();
+ return client.futureReadString();
+ }
+
+
+
+
+ public<T> Future<T> update(String pathinfo, final RosettaDF<T> df, final T t) throws APIException, CadiException {
+ final ParsePath pp = new ParsePath(pathinfo);
+
+ EClient<CT> client = client();
+ client.setMethod(PUT);
+ client.addHeader(CONTENT_TYPE, typeString(df.getTypeClass()));
+ client.setPathInfo(pp.path());
+ client.setQueryParams(pp.query());
+ client.setFragment(pp.frag());
+
+ client.setPayload(new EClient.Transfer() {
+ @Override
+ public void transfer(OutputStream os) throws IOException, APIException {
+ df.newData().out(type).direct(t,os);
+ }
+ });
+ client.send();
+ return client.future(t);
+ }
+
+ public<T> Future<T> update(String pathinfo, Class<?> cls, final RosettaDF<T> df, final T t) throws APIException, CadiException {
+ final ParsePath pp = new ParsePath(pathinfo);
+
+ EClient<CT> client = client();
+ client.setMethod(PUT);
+ client.addHeader(CONTENT_TYPE, typeString(cls));
+ client.setPathInfo(pp.path());
+ client.setQueryParams(pp.query());
+ client.setFragment(pp.frag());
+
+ client.setPayload(new EClient.Transfer() {
+ @Override
+ public void transfer(OutputStream os) throws IOException, APIException {
+ df.newData().out(type).direct(t,os);
+ }
+ });
+ client.send();
+ return client.future(t);
+ }
+
+
+
+ /**
+ * A method to update with a VOID
+ * @param pathinfo
+ * @param resp
+ * @param expected
+ * @return
+ * @throws APIException
+ * @throws CadiException
+ */
+ public<T> Future<Void> update(String pathinfo) throws APIException, CadiException {
+ final ParsePath pp = new ParsePath(pathinfo);
+
+ EClient<CT> client = client();
+ client.setMethod(PUT);
+ client.addHeader(CONTENT_TYPE, typeString(Void.class));
+ client.setPathInfo(pp.path());
+ client.setQueryParams(pp.query());
+ client.setFragment(pp.frag());
+
+// client.setPayload(new EClient.Transfer() {
+// @Override
+// public void transfer(OutputStream os) throws IOException, APIException {
+// }
+// });
+ client.send();
+ return client.future(null);
+ }
+
+
+ public<T> Future<T> delete(String pathinfo, String contentType, final RosettaDF<T> df, final T t) throws APIException, CadiException {
+ final ParsePath pp = new ParsePath(pathinfo);
+
+ EClient<CT> client = client();
+ client.setMethod(DELETE);
+ client.addHeader(CONTENT_TYPE, contentType);
+ client.setPathInfo(pp.path());
+ client.setQueryParams(pp.query());
+ client.setFragment(pp.frag());
+
+ client.setPayload(new EClient.Transfer() {
+ @Override
+ public void transfer(OutputStream os) throws IOException, APIException {
+ df.newData().out(type).direct(t,os);
+ }
+ });
+ client.send();
+ return client.future(t);
+ }
+
+ public<T> Future<T> delete(String pathinfo, Class<?> cls, final RosettaDF<T> df, final T t) throws APIException, CadiException {
+ final ParsePath pp = new ParsePath(pathinfo);
+
+ EClient<CT> client = client();
+ client.setMethod(DELETE);
+ client.addHeader(CONTENT_TYPE, typeString(cls));
+ client.setPathInfo(pp.path());
+ client.setQueryParams(pp.query());
+ client.setFragment(pp.frag());
+ client.setPayload(new EClient.Transfer() {
+ @Override
+ public void transfer(OutputStream os) throws IOException, APIException {
+ df.newData().out(type).direct(t,os);
+ }
+ });
+ client.send();
+ return client.future(t);
+ }
+
+ public<T> Future<T> delete(String pathinfo, final RosettaDF<T> df, final T t) throws APIException, CadiException {
+ final ParsePath pp = new ParsePath(pathinfo);
+
+ EClient<CT> client = client();
+ client.setMethod(DELETE);
+ client.addHeader(CONTENT_TYPE, typeString(df.getTypeClass()));
+ client.setPathInfo(pp.path());
+ client.setQueryParams(pp.query());
+ client.setFragment(pp.frag());
+ client.setPayload(new EClient.Transfer() {
+ @Override
+ public void transfer(OutputStream os) throws IOException, APIException {
+ df.newData().out(type).direct(t,os);
+ }
+ });
+
+ client.send();
+ return client.future(t);
+ }
+
+
+ public<T> Future<T> delete(String pathinfo, Class<T> cls) throws APIException, CadiException {
+ final ParsePath pp = new ParsePath(pathinfo);
+
+ EClient<CT> client = client();
+ client.setMethod(DELETE);
+ client.addHeader(CONTENT_TYPE, typeString(cls));
+ client.setPathInfo(pp.path());
+ client.setQueryParams(pp.query());
+ client.setFragment(pp.frag());
+
+ client.setPayload(null);
+ client.send();
+ return client.future((T)null);
+ }
+
+ public Future<Void> delete(String pathinfo, String contentType) throws APIException, CadiException {
+ final ParsePath pp = new ParsePath(pathinfo);
+
+ EClient<CT> client = client();
+ client.setMethod(DELETE);
+ client.addHeader(CONTENT_TYPE, contentType);
+ client.setPathInfo(pp.path());
+ client.setQueryParams(pp.query());
+ client.setFragment(pp.frag());
+
+ client.setPayload(null);
+ client.send();
+ return client.future(null);
+ }
+
+ public Future<Void> transfer(final HttpServletRequest req, final HttpServletResponse resp, final String pathParam, final int expected) throws CadiException, APIException {
+ EClient<CT> client = client();
+ URI uri;
+ try {
+ uri = new URI(req.getRequestURI());
+ } catch (Exception e) {
+ throw new CadiException("Invalid incoming URI",e);
+ }
+ String name;
+ for (Enumeration<String> en = req.getHeaderNames();en.hasMoreElements();) {
+ name = en.nextElement();
+ client.addHeader(name,req.getHeader(name));
+ }
+ client.setQueryParams(req.getQueryString());
+ client.setFragment(uri.getFragment());
+ client.setPathInfo(pathParam);
+ String meth = req.getMethod();
+ client.setMethod(meth);
+ if (!"GET".equals(meth)) {
+ client.setPayload(new EClient.Transfer() {
+ @Override
+ public void transfer(OutputStream os) throws IOException, APIException {
+ final ServletInputStream is = req.getInputStream();
+ int read;
+ // reuse Buffers
+ Pooled<byte[]> pbuff = buffPool.get();
+ try {
+ while ((read=is.read(pbuff.content))>=0) {
+ os.write(pbuff.content,0,read);
+ }
+ } finally {
+ pbuff.done();
+ }
+ }
+ });
+ }
+ client.send();
+ return client.future(resp, expected);
+ }
+
+ private class ParsePath {
+ private final String path;
+ private final int query;
+ private final int queryEnd;
+ private final int pound;
+ private final String queryParams;
+
+ public ParsePath(final String origPath) {
+ path = origPath;
+ if (origPath==null) {
+ query=queryEnd=pound=-1;
+ queryParams=null;
+ } else {
+ query = origPath.indexOf('?');
+ pound = origPath.indexOf('#');
+ queryEnd = pound>=0?pound:path.length();
+ if (oneCallQueryParams==null) {
+ if (query>=0) {
+ queryParams = path.substring(query+1,queryEnd);
+ } else {
+ queryParams=null;
+ }
+ } else {
+ if (query>=0) {
+ queryParams = oneCallQueryParams + '&' + path.substring(query+1,queryEnd);
+ } else {
+ queryParams = oneCallQueryParams;
+ }
+ oneCallQueryParams = null;
+ }
+ }
+ }
+
+ public String path() {
+ if (query>=0) {
+ if (pound>=0) {
+ return path.substring(pound+1);
+ }
+ return path.substring(0,query);
+ } else if (pound>=0) {
+ return path.substring(0,pound);
+ } else {
+ return path;
+ }
+ }
+
+ public String query() {
+ return queryParams;
+ }
+
+ public String frag() {
+ if (pound>=0) {
+ return path.substring(pound+1);
+ } else {
+ return null;
+ }
+ }
+ }
+
+ public String toString() {
+ return uri.toString();
+ }
+
+ public URI getURI() {
+ return uri;
+ }
+
+ public void setQueryParams(final String queryParams) {
+ oneCallQueryParams=queryParams;
+ }
}
\ No newline at end of file