FileImportHelper.java 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277
  1. /***************************************************************************************
  2. * IBM Confidential
  3. *
  4. * OCO Source Materials
  5. *
  6. * IBM Cognos Products: Moser
  7. *
  8. * (C) Copyright IBM Corp. 2020
  9. *
  10. * The source code for this program is not published or otherwise
  11. * divested of its trade secrets, irrespective of what has been
  12. * deposited with the U.S. Copyright Office.
  13. *
  14. ***************************************************************************************/
  15. package com.ibm.bi.platform.modeling.sdk.examples;
  16. import static com.ibm.bi.platform.modeling.sdk.examples.ModelingRESTEndpoints.filesURL;
  17. import java.io.ByteArrayInputStream;
  18. import java.io.File;
  19. import java.io.IOException;
  20. import java.io.InputStream;
  21. import java.io.UnsupportedEncodingException;
  22. import java.net.URLEncoder;
  23. import java.util.ArrayList;
  24. import org.apache.commons.io.FilenameUtils;
  25. import org.apache.http.Header;
  26. import org.apache.http.HttpEntity;
  27. import org.apache.http.HttpHeaders;
  28. import org.apache.http.client.methods.HttpPost;
  29. import org.apache.http.client.methods.HttpPut;
  30. import org.apache.http.client.methods.HttpRequestBase;
  31. import org.apache.http.entity.ContentType;
  32. import org.apache.http.entity.InputStreamEntity;
  33. import org.apache.http.entity.StringEntity;
  34. import com.ibm.bi.platform.modeling.sdk.examples.internal.UnexpectedHTTPResponseException;
  35. import com.ibm.bi.platform.moser.core.tasks.TaskState;
  36. import com.ibm.json.java.JSONObject;
  37. /**
  38. * Upload new files
  39. *
  40. * Replace existing uploaded files
  41. *
  42. * Append to existing uploaded files
  43. *
  44. */
  45. public class FileImportHelper extends AsynchronousTasksRunner {
  46. private static final String AFFINITY = "x-ca-affinity";
  47. private static final String SEGMENT = "index";
  48. private static final String CSV_TYPE = "text/csv";
  49. private static final String XLS_TYPE = "application/vnd.ms-excel";
  50. private static final String XLSX_TYPE =
  51. "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
  52. public FileImportHelper(String origin) {
  53. super(origin);
  54. }
  55. /**
  56. * Upload file
  57. *
  58. * @param dir
  59. * directory of the source file relative to current
  60. * @param filename
  61. * file name of the file to be uploaded including extension
  62. * @param destination
  63. * folder path or store id
  64. * @return uploaded file response
  65. *
  66. * @throws UnsupportedEncodingException
  67. * @throws IOException
  68. * @throws UnexpectedHTTPResponseException
  69. */
  70. public String uploadFile(String dir, String filename, String destination)
  71. throws UnsupportedEncodingException, IOException, UnexpectedHTTPResponseException {
  72. HttpPost initiate = new HttpPost(getOrigin() + filesURL);
  73. JSONObject parameters = new JSONObject();
  74. parameters.put("filename", filename);
  75. parameters.put("destination", destination);
  76. HttpEntity entity = new StringEntity(parameters.toString());
  77. initiate.setEntity(entity);
  78. initiate.setHeader(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_JSON.getMimeType());
  79. String response = executeUploadRequest(initiate, dir + File.separator + filename, filename, null,
  80. getContentType(filename), 202 );
  81. return executeAsychronousTask(response).toString();
  82. }
  83. /**
  84. * @param filename
  85. * @return
  86. */
  87. private static String getContentType(String filename) {
  88. switch (FilenameUtils.getExtension(filename)) {
  89. case "xls":
  90. return XLS_TYPE;
  91. case "xlsx":
  92. return XLSX_TYPE;
  93. case "csv":
  94. default:
  95. return CSV_TYPE;
  96. }
  97. }
  98. /**
  99. * Replace existing file with new content
  100. *
  101. * @param uploadedFileId
  102. * store id of the file to be replaced
  103. * @param dir
  104. * directory of the source file relative to current
  105. * @param filename
  106. * file name of the file to be uploaded including extension
  107. * @return uploaded file response
  108. *
  109. * @throws UnsupportedEncodingException
  110. * @throws IOException
  111. * @throws UnexpectedHTTPResponseException
  112. */
  113. public String replaceFile(String uploadedFileId, String dir, String filename )
  114. throws UnsupportedEncodingException, IOException, UnexpectedHTTPResponseException {
  115. HttpPut initiate = new HttpPut(getOrigin() + filesURL + "/" + uploadedFileId + "?append=false&filename="
  116. + URLEncoder.encode(filename, "UTF-8"));
  117. String response = executeUploadRequest(initiate, dir + File.separator + filename, filename, null,
  118. getContentType(filename), 202 );
  119. return executeAsychronousTask(response).toString();
  120. }
  121. /**
  122. * Replace existing file with new content
  123. *
  124. * @param uploadedFileId
  125. * store id of the file to be appended
  126. * @param dir
  127. * directory of the source file relative to current
  128. * @param appendFileName
  129. * file name of the file to be uploaded including extension
  130. * @return uploaded file response
  131. *
  132. * @throws UnsupportedEncodingException
  133. * @throws IOException
  134. * @throws UnexpectedHTTPResponseException
  135. */
  136. public String appendFile(String uploadedFileId, String dir, String appendFileName)
  137. throws UnsupportedEncodingException, IOException, UnexpectedHTTPResponseException {
  138. HttpPut initiate = new HttpPut(getOrigin() + filesURL + "/" + uploadedFileId + "?append=true&filename="
  139. + URLEncoder.encode(appendFileName, "UTF-8"));
  140. String response = executeUploadRequest(initiate, dir + File.separator + appendFileName, appendFileName, null,
  141. getContentType(appendFileName), 202 );
  142. return executeAsychronousTask(response).toString();
  143. }
  144. /**
  145. * @param aRequest
  146. * POST or PUT REST request
  147. * @param filename
  148. * name to be used for upload
  149. * @param content_path
  150. * relative to project root file to be uploaded path, e.g. resources/pizza.xlsx
  151. * @param uploadedId existing file store id for replace and append scenarios, null for new uploads
  152. * @param contentType
  153. * @return http response body
  154. * @throws UnsupportedEncodingException
  155. * @throws IOException
  156. * @throws UnexpectedHTTPResponseException
  157. */
  158. private String executeUploadRequest(HttpRequestBase aRequest, String content_path, String filename,
  159. String uploadedId, String contentType, int expectedStatus)
  160. throws UnsupportedEncodingException, IOException, UnexpectedHTTPResponseException {
  161. try (InputStream filedata = streamFromFile(content_path)) {
  162. ArrayList<Header> headers = new ArrayList<>();
  163. // {
  164. // "importPath": "string",
  165. // "href": "string",
  166. // "taskID": "string"
  167. // }
  168. String json = executeHttpRequest(aRequest, expectedStatus, headers);
  169. if( headers.size() == 0) {
  170. throw new UnexpectedHTTPResponseException(null, "Response is missing headers");
  171. }
  172. Header affinity = null;
  173. for (Header header : headers) {
  174. if (AFFINITY.equalsIgnoreCase(header.getName())) {
  175. affinity = header;
  176. break;
  177. }
  178. }
  179. if(affinity == null) {
  180. throw new UnexpectedHTTPResponseException(null, "Affinity should have a non null value");
  181. }
  182. int length = filedata.available();
  183. int buffer_size = length / 10;
  184. JSONObject fileImport = JSONObject.parse(json);
  185. String path = getOrigin() + fileImport.get("importPath");
  186. // issue series of segment PUTs
  187. for (int index = 1; filedata.available() > 0; index++) {
  188. byte[] buffer = new byte[Math.min(buffer_size, filedata.available())];
  189. filedata.read(buffer);
  190. HttpPut request = new HttpPut(path + "?" + SEGMENT + "=" + String.valueOf(index));
  191. request.setHeader(HttpHeaders.CONTENT_TYPE, contentType);
  192. request.setHeader(affinity.getName(), affinity.getValue());
  193. request.setEntity(new InputStreamEntity(new ByteArrayInputStream(buffer)));
  194. executeHttpRequest(request, Integer.valueOf(202), null);
  195. }
  196. // last PUT
  197. HttpPut request = new HttpPut(path + "?" + SEGMENT + "=" + String.valueOf(-1));
  198. request.setHeader(HttpHeaders.CONTENT_TYPE, contentType);
  199. request.setHeader(affinity.getName(), affinity.getValue());
  200. request.setEntity(null);
  201. return executeHttpRequest(request, Integer.valueOf(expectedStatus), null);
  202. }
  203. }
  204. @Override
  205. protected JSONObject executeAsychronousTask(String task){
  206. JSONObject taskResponse = super.executeAsychronousTask(task);
  207. if (TaskState.SUCCESS.equals(taskResponse.get("state"))) {
  208. return (JSONObject) taskResponse.get("response");
  209. }
  210. // return error message
  211. return taskResponse;
  212. }
  213. /* (non-Javadoc)
  214. * @see com.ibm.bi.platform.modeling.sdk.examples.AsynchronousTasksRunner#getTasksURL()
  215. */
  216. @Override
  217. public String getTasksURL() {
  218. return ModelingRESTEndpoints.fileImportTasksURL;
  219. }
  220. }