/*************************************************************************************** * IBM Confidential * * OCO Source Materials * * IBM Cognos Products: Moser * * (C) Copyright IBM Corp. 2020 * * The source code for this program is not published or otherwise * divested of its trade secrets, irrespective of what has been * deposited with the U.S. Copyright Office. * ***************************************************************************************/ package com.ibm.bi.platform.modeling.sdk.examples; import static com.ibm.bi.platform.modeling.sdk.examples.ModelingRESTEndpoints.filesURL; import java.io.ByteArrayInputStream; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.util.ArrayList; import org.apache.commons.io.FilenameUtils; import org.apache.http.Header; import org.apache.http.HttpEntity; import org.apache.http.HttpHeaders; import org.apache.http.client.methods.HttpPost; import org.apache.http.client.methods.HttpPut; import org.apache.http.client.methods.HttpRequestBase; import org.apache.http.entity.ContentType; import org.apache.http.entity.InputStreamEntity; import org.apache.http.entity.StringEntity; import com.ibm.bi.platform.modeling.sdk.examples.internal.UnexpectedHTTPResponseException; import com.ibm.bi.platform.moser.core.tasks.TaskState; import com.ibm.json.java.JSONObject; /** * Upload new files * * Replace existing uploaded files * * Append to existing uploaded files * */ public class FileImportHelper extends AsynchronousTasksRunner { private static final String AFFINITY = "x-ca-affinity"; private static final String SEGMENT = "index"; private static final String CSV_TYPE = "text/csv"; private static final String XLS_TYPE = "application/vnd.ms-excel"; private static final String XLSX_TYPE = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"; public FileImportHelper(String origin) { super(origin); } /** * Upload file * * @param dir * directory of the source file relative to current * @param filename * file name of the file to be uploaded including extension * @param destination * folder path or store id * @return uploaded file response * * @throws UnsupportedEncodingException * @throws IOException * @throws UnexpectedHTTPResponseException */ public String uploadFile(String dir, String filename, String destination) throws UnsupportedEncodingException, IOException, UnexpectedHTTPResponseException { HttpPost initiate = new HttpPost(getOrigin() + filesURL); JSONObject parameters = new JSONObject(); parameters.put("filename", filename); parameters.put("destination", destination); HttpEntity entity = new StringEntity(parameters.toString()); initiate.setEntity(entity); initiate.setHeader(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_JSON.getMimeType()); String response = executeUploadRequest(initiate, dir + File.separator + filename, filename, null, getContentType(filename), 202 ); return executeAsychronousTask(response).toString(); } /** * @param filename * @return */ private static String getContentType(String filename) { switch (FilenameUtils.getExtension(filename)) { case "xls": return XLS_TYPE; case "xlsx": return XLSX_TYPE; case "csv": default: return CSV_TYPE; } } /** * Replace existing file with new content * * @param uploadedFileId * store id of the file to be replaced * @param dir * directory of the source file relative to current * @param filename * file name of the file to be uploaded including extension * @return uploaded file response * * @throws UnsupportedEncodingException * @throws IOException * @throws UnexpectedHTTPResponseException */ public String replaceFile(String uploadedFileId, String dir, String filename ) throws UnsupportedEncodingException, IOException, UnexpectedHTTPResponseException { HttpPut initiate = new HttpPut(getOrigin() + filesURL + "/" + uploadedFileId + "?append=false&filename=" + URLEncoder.encode(filename, "UTF-8")); String response = executeUploadRequest(initiate, dir + File.separator + filename, filename, null, getContentType(filename), 202 ); return executeAsychronousTask(response).toString(); } /** * Replace existing file with new content * * @param uploadedFileId * store id of the file to be appended * @param dir * directory of the source file relative to current * @param appendFileName * file name of the file to be uploaded including extension * @return uploaded file response * * @throws UnsupportedEncodingException * @throws IOException * @throws UnexpectedHTTPResponseException */ public String appendFile(String uploadedFileId, String dir, String appendFileName) throws UnsupportedEncodingException, IOException, UnexpectedHTTPResponseException { HttpPut initiate = new HttpPut(getOrigin() + filesURL + "/" + uploadedFileId + "?append=true&filename=" + URLEncoder.encode(appendFileName, "UTF-8")); String response = executeUploadRequest(initiate, dir + File.separator + appendFileName, appendFileName, null, getContentType(appendFileName), 202 ); return executeAsychronousTask(response).toString(); } /** * @param aRequest * POST or PUT REST request * @param filename * name to be used for upload * @param content_path * relative to project root file to be uploaded path, e.g. resources/pizza.xlsx * @param uploadedId existing file store id for replace and append scenarios, null for new uploads * @param contentType * @return http response body * @throws UnsupportedEncodingException * @throws IOException * @throws UnexpectedHTTPResponseException */ private String executeUploadRequest(HttpRequestBase aRequest, String content_path, String filename, String uploadedId, String contentType, int expectedStatus) throws UnsupportedEncodingException, IOException, UnexpectedHTTPResponseException { try (InputStream filedata = streamFromFile(content_path)) { ArrayList
headers = new ArrayList<>(); // { // "importPath": "string", // "href": "string", // "taskID": "string" // } String json = executeHttpRequest(aRequest, expectedStatus, headers); if( headers.size() == 0) { throw new UnexpectedHTTPResponseException(null, "Response is missing headers"); } Header affinity = null; for (Header header : headers) { if (AFFINITY.equalsIgnoreCase(header.getName())) { affinity = header; break; } } if(affinity == null) { throw new UnexpectedHTTPResponseException(null, "Affinity should have a non null value"); } int length = filedata.available(); int buffer_size = length / 10; JSONObject fileImport = JSONObject.parse(json); String path = getOrigin() + fileImport.get("importPath"); // issue series of segment PUTs for (int index = 1; filedata.available() > 0; index++) { byte[] buffer = new byte[Math.min(buffer_size, filedata.available())]; filedata.read(buffer); HttpPut request = new HttpPut(path + "?" + SEGMENT + "=" + String.valueOf(index)); request.setHeader(HttpHeaders.CONTENT_TYPE, contentType); request.setHeader(affinity.getName(), affinity.getValue()); request.setEntity(new InputStreamEntity(new ByteArrayInputStream(buffer))); executeHttpRequest(request, Integer.valueOf(202), null); } // last PUT HttpPut request = new HttpPut(path + "?" + SEGMENT + "=" + String.valueOf(-1)); request.setHeader(HttpHeaders.CONTENT_TYPE, contentType); request.setHeader(affinity.getName(), affinity.getValue()); request.setEntity(null); return executeHttpRequest(request, Integer.valueOf(expectedStatus), null); } } @Override protected JSONObject executeAsychronousTask(String task){ JSONObject taskResponse = super.executeAsychronousTask(task); if (TaskState.SUCCESS.equals(taskResponse.get("state"))) { return (JSONObject) taskResponse.get("response"); } // return error message return taskResponse; } /* (non-Javadoc) * @see com.ibm.bi.platform.modeling.sdk.examples.AsynchronousTasksRunner#getTasksURL() */ @Override public String getTasksURL() { return ModelingRESTEndpoints.fileImportTasksURL; } }