+++ /dev/null
-/*******************************************************************************\r
- * ============LICENSE_START====================================================\r
- * * org.onap.aaf\r
- * * ===========================================================================\r
- * * Copyright © 2017 AT&T Intellectual Property. All rights reserved.\r
- * * ===========================================================================\r
- * * Licensed under the Apache License, Version 2.0 (the "License");\r
- * * you may not use this file except in compliance with the License.\r
- * * You may obtain a copy of the License at\r
- * * \r
- * * http://www.apache.org/licenses/LICENSE-2.0\r
- * * \r
- * * Unless required by applicable law or agreed to in writing, software\r
- * * distributed under the License is distributed on an "AS IS" BASIS,\r
- * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * * See the License for the specific language governing permissions and\r
- * * limitations under the License.\r
- * * ============LICENSE_END====================================================\r
- * *\r
- * * ECOMP is a trademark and service mark of AT&T Intellectual Property.\r
- * *\r
- ******************************************************************************/\r
-package org.onap.aaf.cadi.http;\r
-\r
-import java.io.IOException;\r
-import java.io.InputStream;\r
-import java.io.InputStreamReader;\r
-import java.io.OutputStream;\r
-import java.io.Reader;\r
-import java.net.HttpURLConnection;\r
-import java.net.URI;\r
-import java.net.URL;\r
-import java.util.ArrayList;\r
-\r
-import javax.servlet.http.HttpServletResponse;\r
-\r
-import org.onap.aaf.cadi.CadiException;\r
-import org.onap.aaf.cadi.LocatorException;\r
-import org.onap.aaf.cadi.SecuritySetter;\r
-import org.onap.aaf.cadi.client.EClient;\r
-import org.onap.aaf.cadi.client.Future;\r
-import org.onap.aaf.cadi.client.Rcli;\r
-\r
-import org.onap.aaf.inno.env.APIException;\r
-import org.onap.aaf.inno.env.Data;\r
-import org.onap.aaf.inno.env.Data.TYPE;\r
-import org.onap.aaf.inno.env.util.Pool.Pooled;\r
-import org.onap.aaf.rosetta.env.RosettaDF;\r
-\r
-/**\r
- * Low Level Http Client Mechanism. Chances are, you want the high level "HRcli"\r
- * for Rosetta Object Translation\r
- * \r
- *\r
- */\r
-public class HClient implements EClient<HttpURLConnection> {\r
- private URI uri;\r
- private ArrayList<Header> headers;\r
- private String meth;\r
- private String pathinfo;\r
- private String query;\r
- private String fragment;\r
- private Transfer transfer;\r
- private SecuritySetter<HttpURLConnection> ss;\r
- private HttpURLConnection huc;\r
- private int connectTimeout;\r
-\r
- public HClient(SecuritySetter<HttpURLConnection> ss, URI uri,int connectTimeout) throws LocatorException {\r
- if (uri == null) {\r
- throw new LocatorException("No Service available to call");\r
- }\r
- this.uri = uri;\r
- this.ss = ss;\r
- this.connectTimeout = connectTimeout;\r
- pathinfo = query = fragment = ""; \r
- }\r
-\r
- @Override\r
- public void setMethod(String meth) {\r
- this.meth = meth;\r
- }\r
-\r
- @Override\r
- public void setPathInfo(String pathinfo) {\r
- this.pathinfo = pathinfo;\r
- }\r
-\r
- @Override\r
- public void setPayload(Transfer transfer) {\r
- this.transfer = transfer;\r
- }\r
- \r
- @Override\r
- public void addHeader(String tag, String value) {\r
- if (headers == null)\r
- headers = new ArrayList<Header>();\r
- headers.add(new Header(tag, value));\r
- }\r
-\r
- @Override\r
- public void setQueryParams(String q) {\r
- query = q;\r
- }\r
-\r
- @Override\r
- public void setFragment(String f) {\r
- fragment = f;\r
- }\r
-\r
- @Override\r
- public void send() throws APIException {\r
- try {\r
- // Build URL from given URI plus current Settings\r
- if(uri.getPath()==null) {\r
- throw new APIException("Invalid URL entered for HClient");\r
- }\r
- StringBuilder pi = new StringBuilder(uri.getPath());\r
- if(!pathinfo.startsWith("/")) {\r
- pi.append('/');\r
- }\r
- pi.append(pathinfo);\r
- URL url = new URI(\r
- uri.getScheme(), \r
- uri.getUserInfo(),\r
- uri.getHost(), \r
- uri.getPort(), \r
- pi.toString(), \r
- query,\r
- fragment).toURL();\r
- pathinfo=null;\r
- query=null;\r
- fragment=null;\r
- huc = (HttpURLConnection) url.openConnection();\r
- if(ss!=null) {\r
- ss.setSecurity(huc); \r
- }\r
- huc.setRequestMethod(meth);\r
- if (headers != null)\r
- for (Header d : headers) {\r
- huc.addRequestProperty(d.tag, d.value);\r
- }\r
- huc.setDoInput(true);\r
- huc.setDoOutput(true);\r
- huc.setUseCaches(false);\r
- huc.setConnectTimeout(connectTimeout);\r
- huc.connect();\r
- if (transfer != null) {\r
- transfer.transfer(huc.getOutputStream());\r
- }\r
- // TODO other settings? There's a bunch here.\r
- } catch (Exception e) {\r
- throw new APIException(e);\r
- } finally { // ensure all these are reset after sends\r
- meth=pathinfo=null;\r
- if(headers!=null) {\r
- headers.clear();\r
- }\r
- pathinfo = query = fragment = "";\r
- }\r
- }\r
-\r
- public abstract class HFuture<T> extends Future<T> {\r
- protected HttpURLConnection huc;\r
- protected int respCode;\r
- protected String respMessage;\r
- protected IOException exception;\r
- protected StringBuilder errContent;\r
- \r
- public HFuture(final HttpURLConnection huc) {\r
- this.huc = huc;\r
- }\r
- \r
- protected boolean evalInfo(HttpURLConnection huc) throws APIException, IOException{\r
- return respCode == 200;\r
- };\r
- \r
- @Override\r
- public final boolean get(int timeout) throws CadiException {\r
- try {\r
- huc.setReadTimeout(timeout);\r
- respCode = huc.getResponseCode();\r
- ss.setLastResponse(respCode);\r
- if(evalInfo(huc)) {\r
- return true;\r
- } else {\r
- extractError();\r
- return false;\r
- }\r
- } catch (IOException | APIException e) {\r
- throw new CadiException(e);\r
- } finally {\r
- close();\r
- }\r
- }\r
- \r
- private void extractError() {\r
- InputStream is = huc.getErrorStream();\r
- try {\r
- if(is==null) {\r
- is = huc.getInputStream();\r
- }\r
- if(is!=null) {\r
- errContent = new StringBuilder();\r
- int c;\r
- while((c=is.read())>=0) {\r
- errContent.append((char)c);\r
- }\r
- }\r
- } catch (IOException e) {\r
- exception = e;\r
- }\r
- }\r
- \r
- // Typically only used by Read\r
- public StringBuilder inputStreamToString(InputStream is) {\r
- // Avoids Carriage returns, and is reasonably efficient, given\r
- // the buffer reads.\r
- try {\r
- StringBuilder sb = new StringBuilder();\r
- Reader rdr = new InputStreamReader(is);\r
- try {\r
- char[] buf = new char[256];\r
- int read;\r
- while ((read = rdr.read(buf)) >= 0) {\r
- sb.append(buf, 0, read);\r
- }\r
- } finally {\r
- rdr.close();\r
- }\r
- return sb;\r
- } catch (IOException e) {\r
- exception = e;\r
- return null;\r
- }\r
- }\r
- \r
- \r
- @Override\r
- public int code() {\r
- return respCode;\r
- }\r
- \r
- public HttpURLConnection huc() {\r
- return huc;\r
- }\r
- \r
- public IOException exception() {\r
- return exception;\r
- }\r
- \r
- public String respMessage() {\r
- return respMessage;\r
- }\r
- \r
- @Override\r
- public String header(String tag) {\r
- return huc.getHeaderField(tag);\r
- }\r
- \r
- public void close() {\r
- if(huc!=null) {\r
- huc.disconnect();\r
- }\r
- }\r
- }\r
-\r
- @Override\r
- public <T> Future<T> futureCreate(Class<T> t) {\r
- return new HFuture<T>(huc) {\r
- public boolean evalInfo(HttpURLConnection huc) {\r
- return respCode==201;\r
- }\r
-\r
- @Override\r
- public String body() {\r
- if (errContent != null) {\r
- return errContent.toString();\r
- \r
- } else if (respMessage != null) {\r
- return respMessage;\r
- }\r
- return "";\r
- }\r
- };\r
- }\r
-\r
- @Override\r
- public Future<String> futureReadString() {\r
- return new HFuture<String>(huc) {\r
- public boolean evalInfo(HttpURLConnection huc) throws IOException {\r
- if (respCode == 200) {\r
- StringBuilder sb = inputStreamToString(huc.getInputStream());\r
- if (sb != null) {\r
- value = sb.toString();\r
- }\r
- return true;\r
- }\r
- return false;\r
- }\r
-\r
- @Override\r
- public String body() {\r
- if (value != null) {\r
- return value;\r
- } else if (errContent != null) {\r
- return errContent.toString();\r
- } else if (respMessage != null) {\r
- return respMessage;\r
- }\r
- return "";\r
- }\r
-\r
- };\r
- }\r
-\r
- @Override\r
- public <T> Future<T> futureRead(final RosettaDF<T> df, final TYPE type) {\r
- return new HFuture<T>(huc) {\r
- private Data<T> data;\r
-\r
- public boolean evalInfo(HttpURLConnection huc) throws APIException, IOException {\r
- if (respCode == 200) {\r
- data = df.newData().in(type).load(huc.getInputStream());\r
- value = data.asObject();\r
- return true;\r
- }\r
- return false;\r
- }\r
-\r
- @Override\r
- public String body() {\r
- if (data != null) {\r
- try {\r
- return data.asString();\r
- } catch (APIException e) {\r
- }\r
- } else if (errContent != null) {\r
- return errContent.toString();\r
- } else if (respMessage != null) {\r
- return respMessage;\r
- }\r
- return "";\r
- }\r
- };\r
- }\r
-\r
- @Override\r
- public <T> Future<T> future(final T t) {\r
- return new HFuture<T>(huc) {\r
- public boolean evalInfo(HttpURLConnection huc) {\r
- if (respCode == 200) {\r
- value = t;\r
- return true;\r
- }\r
- return false;\r
- }\r
-\r
- @Override\r
- public String body() {\r
- if (errContent != null) {\r
- return errContent.toString();\r
- } else if (respMessage != null) {\r
- return respMessage;\r
- }\r
- return Integer.toString(respCode);\r
- }\r
- };\r
- }\r
-\r
- @Override\r
- public Future<Void> future(final HttpServletResponse resp, final int expected) throws APIException {\r
- return new HFuture<Void>(huc) {\r
- public boolean evalInfo(HttpURLConnection huc) throws IOException, APIException {\r
- resp.setStatus(respCode);\r
- int read;\r
- InputStream is;\r
- OutputStream os = resp.getOutputStream();\r
- if(respCode==expected) {\r
- is = huc.getInputStream();\r
- // reuse Buffers\r
- Pooled<byte[]> pbuff = Rcli.buffPool.get();\r
- try { \r
- while((read=is.read(pbuff.content))>=0) {\r
- os.write(pbuff.content,0,read);\r
- }\r
- } finally {\r
- pbuff.done();\r
- }\r
- return true;\r
- } else {\r
- is = huc.getErrorStream();\r
- if(is==null) {\r
- is = huc.getInputStream();\r
- }\r
- if(is!=null) {\r
- errContent = new StringBuilder();\r
- Pooled<byte[]> pbuff = Rcli.buffPool.get();\r
- try { \r
- while((read=is.read(pbuff.content))>=0) {\r
- os.write(pbuff.content,0,read);\r
- }\r
- } finally {\r
- pbuff.done();\r
- }\r
- }\r
- }\r
- return false;\r
- }\r
-\r
- @Override\r
- public String body() {\r
- return errContent==null?respMessage:errContent.toString();\r
- }\r
- };\r
- }\r
-\r
- private static class Header {\r
- public final String tag;\r
- public final String value;\r
-\r
- public Header(String t, String v) {\r
- this.tag = t;\r
- this.value = v;\r
- }\r
- \r
- public String toString() {\r
- return tag + '=' + value;\r
- }\r
- }\r
- \r
- public String toString() {\r
- return "HttpURLConnection Client configured to " + uri.toString();\r
- }\r
-}\r