com.smartsheet.api.internal.AbstractResources Maven / Gradle / Ivy
Show all versions of smartsheet-sdk-java Show documentation
/*
* Copyright (C) 2024 Smartsheet
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.smartsheet.api.internal;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.smartsheet.api.AuthorizationException;
import com.smartsheet.api.InvalidRequestException;
import com.smartsheet.api.ResourceNotFoundException;
import com.smartsheet.api.ServiceUnavailableException;
import com.smartsheet.api.SmartsheetException;
import com.smartsheet.api.SmartsheetRestException;
import com.smartsheet.api.internal.http.HttpEntity;
import com.smartsheet.api.internal.http.HttpMethod;
import com.smartsheet.api.internal.http.HttpRequest;
import com.smartsheet.api.internal.http.HttpResponse;
import com.smartsheet.api.internal.json.JSONSerializerException;
import com.smartsheet.api.internal.util.StreamUtil;
import com.smartsheet.api.internal.util.Util;
import com.smartsheet.api.models.Attachment;
import com.smartsheet.api.models.CopyOrMoveRowDirective;
import com.smartsheet.api.models.CopyOrMoveRowResult;
import com.smartsheet.api.models.PagedResult;
import com.smartsheet.api.models.Result;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.InvocationTargetException;
import java.net.URI;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* This is the base class of the Smartsheet REST API resources.
*
* Thread Safety: This class is thread safe because it is immutable and the underlying SmartsheetImpl is thread safe.
*/
public abstract class AbstractResources {
/**
* this system property is used to control the number of characters logged from an API response in logs
*/
public static final String PROPERTY_RESPONSE_LOG_CHARS = "Smartsheet.responseLogChars";
private static final Logger log = LoggerFactory.getLogger(AbstractResources.class);
/**
* The Constant BUFFER_SIZE.
*/
private static final int BUFFER_SIZE = 4098;
private static final String JSON_CONTENT_TYPE = "application/json";
private static final String HEADER_CONTENT_TYPE = "Content-Type";
/**
* The Enum ErrorCode.
*/
public enum ErrorCode {
BAD_REQUEST(400, InvalidRequestException.class),
NOT_AUTHORIZED(401, AuthorizationException.class),
FORBIDDEN(403, AuthorizationException.class),
NOT_FOUND(404, ResourceNotFoundException.class),
METHOD_NOT_SUPPORTED(405, InvalidRequestException.class),
INTERNAL_SERVER_ERROR(500, InvalidRequestException.class),
SERVICE_UNAVAILABLE(503, ServiceUnavailableException.class);
/**
* The error code.
*/
int errorCode;
/**
* The Exception class.
*/
Class extends SmartsheetRestException> exceptionClass;
/**
* Instantiates a new error code.
*
* @param errorCode the error code
* @param exceptionClass the Exception class
*/
ErrorCode(int errorCode, Class extends SmartsheetRestException> exceptionClass) {
this.errorCode = errorCode;
this.exceptionClass = exceptionClass;
}
/**
* Gets the error code.
*
* @param errorNumber the error number
* @return the error code
*/
public static ErrorCode getErrorCode(int errorNumber) {
for (ErrorCode code : ErrorCode.values()) {
if (code.errorCode == errorNumber) {
return code;
}
}
return null;
}
/**
* Gets the exception.
*
* @return the exception
* @throws InstantiationException the instantiation exception
* @throws IllegalAccessException the illegal access exception
*/
public SmartsheetRestException getException() throws InstantiationException, IllegalAccessException {
return exceptionClass.newInstance();
}
/**
* Gets the exception.
*
* @param error the error
* @return the exception
* @throws SmartsheetException the smartsheet exception
*/
public SmartsheetRestException getException(com.smartsheet.api.models.Error error) throws SmartsheetException {
try {
return exceptionClass.getConstructor(com.smartsheet.api.models.Error.class).newInstance(error);
} catch (IllegalArgumentException e) {
throw new SmartsheetException(e);
} catch (SecurityException e) {
throw new SmartsheetException(e);
} catch (InstantiationException e) {
throw new SmartsheetException(e);
} catch (IllegalAccessException e) {
throw new SmartsheetException(e);
} catch (InvocationTargetException e) {
throw new SmartsheetException(e);
} catch (NoSuchMethodException e) {
throw new SmartsheetException(e);
}
}
}
/**
* Represents the SmartsheetImpl.
*
* It will be initialized in constructor and will not change afterwards.
*/
protected final SmartsheetImpl smartsheet;
/**
* Constructor.
*
* @param smartsheet the smartsheet
*/
protected AbstractResources(SmartsheetImpl smartsheet) {
Util.throwIfNull(smartsheet);
this.smartsheet = smartsheet;
}
/**
* Get a resource from Smartsheet REST API.
*
* Parameters: - path : the relative path of the resource - objectClass : the resource object class
*
* Returns: the resource (note that if there is no such resource, this method will throw ResourceNotFoundException
* rather than returning null).
*
* Exceptions: -
* InvalidRequestException : if there is any problem with the REST API request
* AuthorizationException : if there is any problem with the REST API authorization(access token)
* ResourceNotFoundException : if the resource can not be found
* ServiceUnavailableException : if the REST API service is not available (possibly due to rate limiting)
* SmartsheetRestException : if there is any other REST API related error occurred during the operation
* SmartsheetException : if there is any other error occurred during the operation
*
* @param the generic type
* @param path the relative path of the resource.
* @param objectClass the object class
* @return the resource
* @throws SmartsheetException the smartsheet exception
*/
protected T getResource(String path, Class objectClass) throws SmartsheetException {
Util.throwIfNull(path, objectClass);
if (path.isEmpty()) {
com.smartsheet.api.models.Error error = new com.smartsheet.api.models.Error();
error.setMessage("An empty path was provided.");
throw new ResourceNotFoundException(error);
}
HttpRequest request = createHttpRequest(smartsheet.getBaseURI().resolve(path), HttpMethod.GET);
T obj = null;
String content = null;
try {
HttpResponse response = this.smartsheet.getHttpClient().request(request);
InputStream inputStream = response.getEntity().getContent();
switch (response.getStatusCode()) {
case 200:
try {
if (log.isInfoEnabled()) {
ByteArrayOutputStream contentCopyStream = new ByteArrayOutputStream();
inputStream = StreamUtil.cloneContent(inputStream, response.getEntity().getContentLength(), contentCopyStream);
content = StreamUtil.toUtf8StringOrHex(contentCopyStream, getResponseLogLength());
}
obj = this.smartsheet.getJsonSerializer().deserialize(objectClass, inputStream);
} catch (JsonParseException e) {
log.info("failure parsing '{}'", content, e);
throw new SmartsheetException(e);
} catch (JsonMappingException e) {
log.info("failure mapping '{}'", content, e);
throw new SmartsheetException(e);
} catch (IOException e) {
log.info("failure loading '{}'", content, e);
throw new SmartsheetException(e);
}
break;
default:
handleError(response);
}
} catch (JSONSerializerException jsx) {
log.info("failed to parse '{}'", content, jsx);
throw jsx;
} finally {
smartsheet.getHttpClient().releaseConnection();
}
return obj;
}
/**
* Create a resource using Smartsheet REST API.
*
* Exceptions:
* IllegalArgumentException : if any argument is null, or path is empty string
* InvalidRequestException : if there is any problem with the REST API request
* AuthorizationException : if there is any problem with the REST API authorization(access token)
* ServiceUnavailableException : if the REST API service is not available (possibly due to rate limiting)
* SmartsheetRestException : if there is any other REST API related error occurred during the operation
* SmartsheetException : if there is any other error occurred during the operation
*
* @param the generic type of object to return/deserialize
* @param the generic type of object to serialize
* @param path the relative path of the resource collections
* @param objectClass the resource object class
* @param object the object to create
* @return the created resource
* @throws SmartsheetException the smartsheet exception
*/
protected T createResource(String path, Class objectClass, S object) throws SmartsheetException {
Util.throwIfNull(path, object, objectClass);
Util.throwIfEmpty(path);
HttpRequest request = createHttpRequest(smartsheet.getBaseURI().resolve(path), HttpMethod.POST);
ByteArrayOutputStream objectBytesStream = new ByteArrayOutputStream();
this.smartsheet.getJsonSerializer().serialize(object, objectBytesStream);
HttpEntity entity = new HttpEntity();
entity.setContentType(JSON_CONTENT_TYPE);
entity.setContent(new ByteArrayInputStream(objectBytesStream.toByteArray()));
entity.setContentLength(objectBytesStream.size());
request.setEntity(entity);
T obj = null;
try {
HttpResponse response = this.smartsheet.getHttpClient().request(request);
switch (response.getStatusCode()) {
case 200: {
InputStream inputStream = response.getEntity().getContent();
String content = null;
try {
if (log.isInfoEnabled()) {
ByteArrayOutputStream contentCopyStream = new ByteArrayOutputStream();
inputStream = StreamUtil.cloneContent(inputStream, response.getEntity().getContentLength(), contentCopyStream);
content = StreamUtil.toUtf8StringOrHex(contentCopyStream, getResponseLogLength());
}
obj = this.smartsheet.getJsonSerializer().deserializeResult(objectClass, inputStream).getResult();
} catch (JSONSerializerException e) {
log.info("failure parsing '{}'", content, e);
throw new SmartsheetException(e);
} catch (IOException e) {
log.info("failure cloning content from inputStream '{}'", inputStream, e);
throw new SmartsheetException(e);
}
break;
}
default:
handleError(response);
}
} finally {
smartsheet.getHttpClient().releaseConnection();
}
return obj;
}
/**
* Create a resource using Smartsheet REST API.
*
* Exceptions:
* IllegalArgumentException : if any argument is null, or path is empty string
* InvalidRequestException : if there is any problem with the REST API request
* AuthorizationException : if there is any problem with the REST API authorization(access token)
* ServiceUnavailableException : if the REST API service is not available (possibly due to rate limiting)
* SmartsheetRestException : if there is any other REST API related error occurred during the operation
* SmartsheetException : if there is any other error occurred during the operation
*
* @param the generic type
* @param path the relative path of the resource collections
* @param objectClass the resource object class
* @param object the object to create
* @return the created resource
* @throws SmartsheetException the smartsheet exception
*/
protected T createResourceWithAttachment(
String path,
Class objectClass,
T object,
String partName,
InputStream inputStream,
String contentType,
String attachmentName
) throws SmartsheetException {
Util.throwIfNull(path, object);
Util.throwIfEmpty(path);
HttpRequest request;
final String boundary = "----" + System.currentTimeMillis();
CloseableHttpClient httpClient = HttpClients.createDefault();
HttpPost uploadFile = createHttpPost(this.getSmartsheet().getBaseURI().resolve(path));
try {
uploadFile.setHeader(HEADER_CONTENT_TYPE, "multipart/form-data; boundary=" + boundary);
} catch (Exception e) {
throw new RuntimeException(e);
}
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.setBoundary(boundary);
builder.addTextBody(partName, this.getSmartsheet().getJsonSerializer().serialize(object), ContentType.APPLICATION_JSON);
builder.addBinaryBody("file", inputStream, ContentType.create(contentType), attachmentName);
org.apache.http.HttpEntity multipart = builder.build();
uploadFile.setEntity(multipart);
T obj = null;
//implement switch case
try {
CloseableHttpResponse response = httpClient.execute(uploadFile);
org.apache.http.HttpEntity responseEntity = response.getEntity();
obj = this.getSmartsheet().getJsonSerializer().deserializeResult(objectClass,
responseEntity.getContent()).getResult();
} catch (Exception e) {
throw new RuntimeException(e);
}
return obj;
}
/**
* Update a resource using Smartsheet REST API.
*
* Exceptions:
* IllegalArgumentException : if any argument is null, or path is empty string
* InvalidRequestException : if there is any problem with the REST API request
* AuthorizationException : if there is any problem with the REST API authorization(access token)
* ResourceNotFoundException : if the resource can not be found
* ServiceUnavailableException : if the REST API service is not available (possibly due to rate limiting)
* SmartsheetRestException : if there is any other REST API related error occurred during the operation
* SmartsheetException : if there is any other error occurred during the operation
*
* @param the generic type
* @param path the relative path of the resource
* @param objectClass the resource object class
* @param object the object to create
* @return the updated resource
* @throws SmartsheetException the smartsheet exception
*/
protected T updateResource(String path, Class objectClass, T object) throws SmartsheetException {
Util.throwIfNull(path, object);
Util.throwIfEmpty(path);
HttpRequest request;
request = createHttpRequest(smartsheet.getBaseURI().resolve(path), HttpMethod.PUT);
ByteArrayOutputStream objectBytesStream = new ByteArrayOutputStream();
this.smartsheet.getJsonSerializer().serialize(object, objectBytesStream);
HttpEntity entity = new HttpEntity();
entity.setContentType(JSON_CONTENT_TYPE);
entity.setContent(new ByteArrayInputStream(objectBytesStream.toByteArray()));
entity.setContentLength(objectBytesStream.size());
request.setEntity(entity);
T obj = null;
try {
HttpResponse response = this.smartsheet.getHttpClient().request(request);
switch (response.getStatusCode()) {
case 200:
obj = this.smartsheet.getJsonSerializer().deserializeResult(objectClass,
response.getEntity().getContent()).getResult();
break;
default:
handleError(response);
}
} finally {
smartsheet.getHttpClient().releaseConnection();
}
return obj;
}
/**
* List resources using Smartsheet REST API.
*
* Exceptions:
* IllegalArgumentException : if any argument is null, or path is empty string
* InvalidRequestException : if there is any problem with the REST API request
* AuthorizationException : if there is any problem with the REST API authorization(access token)
* ServiceUnavailableException : if the REST API service is not available (possibly due to rate limiting)
* SmartsheetRestException : if there is any other REST API related error occurred during the operation
* SmartsheetException : if there is any other error occurred during the operation
*
* @param the generic type
* @param path the relative path of the resource collections
* @param objectClass the resource object class
* @return the resources
* @throws SmartsheetException if an error occurred during the operation
*/
protected List listResources(String path, Class objectClass) throws SmartsheetException {
Util.throwIfNull(path, objectClass);
Util.throwIfEmpty(path);
HttpRequest request;
request = createHttpRequest(smartsheet.getBaseURI().resolve(path), HttpMethod.GET);
List obj = null;
try {
HttpResponse response = this.smartsheet.getHttpClient().request(request);
switch (response.getStatusCode()) {
case 200:
obj = this.smartsheet.getJsonSerializer().deserializeList(objectClass,
response.getEntity().getContent());
break;
default:
handleError(response);
}
} finally {
smartsheet.getHttpClient().releaseConnection();
}
return obj;
}
/**
* List resources Wrapper (supports paging info) using Smartsheet REST API.
*
* @throws IllegalArgumentException : if any argument is null, or path is empty string
* @throws InvalidRequestException : if there is any problem with the REST API request
* @throws AuthorizationException : if there is any problem with the REST API authorization(access token)
* @throws ServiceUnavailableException : if the REST API service is not available (possibly due to rate limiting)
* @throws SmartsheetRestException : if there is any other REST API related error occurred during the operation
* @throws SmartsheetException : if there is any other error occurred during the operation
*/
protected PagedResult listResourcesWithWrapper(String path, Class objectClass) throws SmartsheetException {
Util.throwIfNull(path, objectClass);
Util.throwIfEmpty(path);
HttpRequest request;
request = createHttpRequest(smartsheet.getBaseURI().resolve(path), HttpMethod.GET);
PagedResult obj = null;
try {
HttpResponse response = this.smartsheet.getHttpClient().request(request);
switch (response.getStatusCode()) {
case 200:
obj = this.smartsheet.getJsonSerializer().deserializeDataWrapper(objectClass,
response.getEntity().getContent());
break;
default:
handleError(response);
}
} finally {
smartsheet.getHttpClient().releaseConnection();
}
return obj;
}
/**
* Delete a resource from Smartsheet REST API.
*
* Exceptions:
* IllegalArgumentException : if any argument is null, or path is empty string
* InvalidRequestException : if there is any problem with the REST API request
* AuthorizationException : if there is any problem with the REST API authorization(access token)
* ResourceNotFoundException : if the resource can not be found
* ServiceUnavailableException : if the REST API service is not available (possibly due to rate limiting)
* SmartsheetRestException : if there is any other REST API related error occurred during the operation
* SmartsheetException : if there is any other error occurred during the operation
*
* @param the generic type
* @param path the relative path of the resource
* @param objectClass the resource object class
* @throws SmartsheetException the smartsheet exception
*/
protected void deleteResource(String path, Class objectClass) throws SmartsheetException {
Util.throwIfNull(path, objectClass);
Util.throwIfEmpty(path);
HttpRequest request;
request = createHttpRequest(smartsheet.getBaseURI().resolve(path), HttpMethod.DELETE);
try {
HttpResponse response = this.smartsheet.getHttpClient().request(request);
switch (response.getStatusCode()) {
case 200:
this.smartsheet.getJsonSerializer().deserializeResult(objectClass,
response.getEntity().getContent());
break;
default:
handleError(response);
}
} finally {
smartsheet.getHttpClient().releaseConnection();
}
}
/**
* Delete resources and return a list from Smartsheet REST API.
*
* Exceptions:
* IllegalArgumentException : if any argument is null, or path is empty string
* InvalidRequestException : if there is any problem with the REST API request
* AuthorizationException : if there is any problem with the REST API authorization(access token)
* ResourceNotFoundException : if the resource can not be found
* ServiceUnavailableException : if the REST API service is not available (possibly due to rate limiting)
* SmartsheetRestException : if there is any other REST API related error occurred during the operation
* SmartsheetException : if there is any other error occurred during the operation
*
* @param the generic type
* @param path the relative path of the resource
* @param objectClass the resource object class
* @return List of ids deleted
* @throws SmartsheetException the smartsheet exception
*/
protected List deleteListResources(String path, Class objectClass) throws SmartsheetException {
Util.throwIfNull(path, objectClass);
Util.throwIfEmpty(path);
Result> obj = null;
HttpRequest request;
request = createHttpRequest(smartsheet.getBaseURI().resolve(path), HttpMethod.DELETE);
try {
HttpResponse response = this.smartsheet.getHttpClient().request(request);
switch (response.getStatusCode()) {
case 200:
obj = this.smartsheet.getJsonSerializer().deserializeListResult(objectClass,
response.getEntity().getContent());
break;
default:
handleError(response);
}
} finally {
smartsheet.getHttpClient().releaseConnection();
}
return obj.getResult();
}
/**
* Post an object to Smartsheet REST API and receive a list of objects from response.
*
* Parameters: - path : the relative path of the resource collections - objectToPost : the object to post -
* objectClassToReceive : the resource object class to receive
*
* Returns: the object list
*
* Exceptions:
* IllegalArgumentException : if any argument is null, or path is empty string
* InvalidRequestException : if there is any problem with the REST API request
* AuthorizationException : if there is any problem with the REST API authorization(access token)
* ServiceUnavailableException : if the REST API service is not available (possibly due to rate limiting)
* SmartsheetRestException : if there is any other REST API related error occurred during the operation
* SmartsheetException : if there is any other error occurred during the operation
*
* @param the generic type
* @param the generic type
* @param path the path
* @param objectToPost the object to post
* @param objectClassToReceive the object class to receive
* @return the list
* @throws SmartsheetException the smartsheet exception
*/
protected List postAndReceiveList(String path, T objectToPost, Class objectClassToReceive) throws SmartsheetException {
Util.throwIfNull(path, objectToPost, objectClassToReceive);
Util.throwIfEmpty(path);
HttpRequest request = createHttpRequest(smartsheet.getBaseURI().resolve(path), HttpMethod.POST);
ByteArrayOutputStream objectBytesStream = new ByteArrayOutputStream();
this.smartsheet.getJsonSerializer().serialize(objectToPost, objectBytesStream);
HttpEntity entity = new HttpEntity();
entity.setContentType(JSON_CONTENT_TYPE);
entity.setContent(new ByteArrayInputStream(objectBytesStream.toByteArray()));
entity.setContentLength(objectBytesStream.size());
request.setEntity(entity);
List obj = null;
try {
HttpResponse response = this.smartsheet.getHttpClient().request(request);
switch (response.getStatusCode()) {
case 200:
obj = this.smartsheet.getJsonSerializer().deserializeListResult(objectClassToReceive,
response.getEntity().getContent()).getResult();
break;
default:
handleError(response);
}
} finally {
smartsheet.getHttpClient().releaseConnection();
}
return obj;
}
/**
* Post an object to Smartsheet REST API and receive a CopyOrMoveRowResult object from response.
*
* Parameters: - path : the relative path of the resource collections - objectToPost : the object to post -
*
* Returns: the object
*
* Exceptions:
* IllegalArgumentException : if any argument is null, or path is empty string
* InvalidRequestException : if there is any problem with the REST API request
* AuthorizationException : if there is any problem with the REST API authorization(access token)
* ServiceUnavailableException : if the REST API service is not available (possibly due to rate limiting)
* SmartsheetRestException : if there is any other REST API related error occurred during the operation
* SmartsheetException : if there is any other error occurred during the operation
*
* @param path the path
* @param objectToPost the object to post
* @return the result object
* @throws SmartsheetException the smartsheet exception
*/
protected CopyOrMoveRowResult postAndReceiveRowObject(String path, CopyOrMoveRowDirective objectToPost) throws SmartsheetException {
Util.throwIfNull(path, objectToPost);
Util.throwIfEmpty(path);
HttpRequest request = createHttpRequest(smartsheet.getBaseURI().resolve(path), HttpMethod.POST);
ByteArrayOutputStream objectBytesStream = new ByteArrayOutputStream();
this.smartsheet.getJsonSerializer().serialize(objectToPost, objectBytesStream);
HttpEntity entity = new HttpEntity();
entity.setContentType(JSON_CONTENT_TYPE);
entity.setContent(new ByteArrayInputStream(objectBytesStream.toByteArray()));
entity.setContentLength(objectBytesStream.size());
request.setEntity(entity);
CopyOrMoveRowResult obj = null;
try {
HttpResponse response = this.smartsheet.getHttpClient().request(request);
switch (response.getStatusCode()) {
case 200:
obj = this.smartsheet.getJsonSerializer().deserializeCopyOrMoveRow(
response.getEntity().getContent());
break;
default:
handleError(response);
}
} finally {
smartsheet.getHttpClient().releaseConnection();
}
return obj;
}
/**
* Put an object to Smartsheet REST API and receive a list of objects from response.
*
* @param the generic type
* @param the generic type
* @param path the relative path of the resource collections
* @param objectToPut the object to put
* @param objectClassToReceive the resource object class to receive
* @return the object list
* @throws IllegalArgumentException : if any argument is null, or path is empty string
* @throws InvalidRequestException : if there is any problem with the REST API request
* @throws AuthorizationException : if there is any problem with the REST API authorization(access token)
* @throws ServiceUnavailableException : if the REST API service is not available (possibly due to rate limiting)
* @throws SmartsheetRestException : if there is any other REST API related error occurred during the operation
* @throws SmartsheetException : if there is any other error occurred during the operation
*/
protected List putAndReceiveList(String path, T objectToPut, Class objectClassToReceive)
throws SmartsheetException {
Util.throwIfNull(path, objectToPut, objectClassToReceive);
Util.throwIfEmpty(path);
HttpRequest request = createHttpRequest(smartsheet.getBaseURI().resolve(path), HttpMethod.PUT);
ByteArrayOutputStream objectBytesStream = new ByteArrayOutputStream();
this.smartsheet.getJsonSerializer().serialize(objectToPut, objectBytesStream);
HttpEntity entity = new HttpEntity();
entity.setContentType(JSON_CONTENT_TYPE);
entity.setContent(new ByteArrayInputStream(objectBytesStream.toByteArray()));
entity.setContentLength(objectBytesStream.size());
request.setEntity(entity);
List obj = null;
try {
HttpResponse response = this.smartsheet.getHttpClient().request(request);
switch (response.getStatusCode()) {
case 200:
obj = this.smartsheet.getJsonSerializer().deserializeListResult(
objectClassToReceive, response.getEntity().getContent()).getResult();
break;
default:
handleError(response);
}
} finally {
smartsheet.getHttpClient().releaseConnection();
}
return obj;
}
/**
* Create an HttpRequest.
*
* @param uri the URI
* @param method the HttpMethod
* @return the http request
*/
protected HttpRequest createHttpRequest(URI uri, HttpMethod method) {
HttpRequest request = new HttpRequest();
request.setUri(uri);
request.setMethod(method);
// Set authorization header
request.setHeaders(createHeaders());
return request;
}
protected HttpPost createHttpPost(URI uri) {
HttpPost httpPost = new HttpPost(uri);
Map headers = createHeaders();
for (Map.Entry entry : headers.entrySet()) {
httpPost.addHeader(entry.getKey(), entry.getValue());
}
return httpPost;
}
/**
* Attach a file
*/
public Attachment attachFile(String url, InputStream inputStream, String contentType, long contentLength, String attachmentName)
throws SmartsheetException {
Util.throwIfNull(inputStream, contentType);
HttpRequest request = createHttpRequest(this.getSmartsheet().getBaseURI().resolve(url), HttpMethod.POST);
request.getHeaders().put(
"Content-Disposition",
"attachment; filename=\"" + URLEncoder.encode(attachmentName, StandardCharsets.UTF_8) + "\""
);
HttpEntity entity = new HttpEntity();
entity.setContentType(contentType);
entity.setContent(new LengthEnforcingInputStream(inputStream, contentLength));
entity.setContentLength(contentLength);
request.setEntity(entity);
Attachment attachment = null;
try {
HttpResponse response = this.getSmartsheet().getHttpClient().request(request);
switch (response.getStatusCode()) {
case 200:
attachment = this.getSmartsheet().getJsonSerializer().deserializeResult(Attachment.class,
response.getEntity().getContent()).getResult();
break;
default:
handleError(response);
}
} finally {
this.getSmartsheet().getHttpClient().releaseConnection();
}
return attachment;
}
/**
* Create a multipart upload request.
*
* @param url the url
* @param t the object to create
* @param partName the name of the part
* @param inputstream the file inputstream
* @param contentType the type of the file to be attached
* @return the http request
* @throws SmartsheetException may be thrown in the method
*/
public Attachment attachFile(String url, T t, String partName, InputStream inputstream, String contentType, String attachmentName)
throws SmartsheetException {
Util.throwIfNull(inputstream, contentType);
Attachment attachment = null;
final String boundary = "----" + System.currentTimeMillis();
CloseableHttpClient httpClient = HttpClients.createDefault();
HttpPost uploadFile = createHttpPost(this.getSmartsheet().getBaseURI().resolve(url));
try {
uploadFile.setHeader(HEADER_CONTENT_TYPE, "multipart/form-data; boundary=" + boundary);
} catch (Exception e) {
throw new RuntimeException(e);
}
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.setBoundary(boundary);
builder.addTextBody(partName, this.getSmartsheet().getJsonSerializer().serialize(t), ContentType.APPLICATION_JSON);
builder.addBinaryBody("file", inputstream, ContentType.create(contentType), attachmentName);
org.apache.http.HttpEntity multipart = builder.build();
uploadFile.setEntity(multipart);
try {
CloseableHttpResponse response = httpClient.execute(uploadFile);
org.apache.http.HttpEntity responseEntity = response.getEntity();
attachment = this.getSmartsheet().getJsonSerializer().deserializeResult(Attachment.class,
responseEntity.getContent()).getResult();
} catch (Exception e) {
throw new RuntimeException(e);
}
return attachment;
}
/**
* Handles an error HttpResponse (non-200) returned by Smartsheet REST API.
*
* @param response the HttpResponse
* @throws SmartsheetException the smartsheet exception
* @throws SmartsheetRestException : the exception corresponding to the error
*/
protected void handleError(HttpResponse response) throws SmartsheetException {
com.smartsheet.api.models.Error error;
try {
error = this.smartsheet.getJsonSerializer().deserialize(
com.smartsheet.api.models.Error.class, response.getEntity().getContent());
} catch (JsonParseException e) {
throw new SmartsheetException(e);
} catch (JsonMappingException e) {
throw new SmartsheetException(e);
} catch (IOException e) {
throw new SmartsheetException(e);
}
ErrorCode code = ErrorCode.getErrorCode(response.getStatusCode());
if (code == null) {
throw new SmartsheetRestException(error);
}
try {
throw code.getException(error);
} catch (IllegalArgumentException e) {
throw new SmartsheetException(e);
} catch (SecurityException e) {
throw new SmartsheetException(e);
}
}
/**
* Gets the smartsheet.
*
* @return the smartsheet
*/
public SmartsheetImpl getSmartsheet() {
return smartsheet;
}
/**
* Get a sheet as a file.
*
* @param path the path
* @param fileType the output file type
* @param outputStream the OutputStream to which the file will be written
* @throws InvalidRequestException : if there is any problem with the REST API request
* @throws AuthorizationException : if there is any problem with the REST API authorization(access token)
* @throws ResourceNotFoundException : if the resource can not be found
* @throws ServiceUnavailableException : if the REST API service is not available (possibly due to rate limiting)
* @throws SmartsheetRestException : if there is any other REST API related error occurred during the operation
* @throws SmartsheetException : if there is any other error occurred during the operation
*/
public void getResourceAsFile(String path, String fileType, OutputStream outputStream)
throws SmartsheetException {
Util.throwIfNull(outputStream, fileType);
HttpRequest request;
request = createHttpRequest(this.getSmartsheet().getBaseURI().resolve(path), HttpMethod.GET);
request.getHeaders().put("Accept", fileType);
try {
HttpResponse response = getSmartsheet().getHttpClient().request(request);
switch (response.getStatusCode()) {
case 200:
try {
copyStream(response.getEntity().getContent(), outputStream);
} catch (IOException e) {
throw new SmartsheetException(e);
}
break;
default:
handleError(response);
}
} finally {
getSmartsheet().getHttpClient().releaseConnection();
}
}
/*
* Copy an input stream to an output stream.
*
* @param input The input stream to copy.
*
* @param output the output stream to write to.
*
* @throws IOException if there is trouble reading or writing to the streams.
*/
/**
* Copy stream.
*
* @param input the input
* @param output the output
* @throws IOException Signals that an I/O exception has occurred.
* @deprecated replace with StreamUtil.copyContentIntoOutputStream()
*/
@Deprecated(since = "2.0.0", forRemoval = true)
private static void copyStream(InputStream input, OutputStream output) throws IOException {
byte[] buffer = new byte[BUFFER_SIZE];
int len;
while ((len = input.read(buffer)) != -1) {
output.write(buffer, 0, len);
}
}
/**
* @return a map of headers to be used when making requests.
*/
Map createHeaders() {
Map headers = new HashMap<>();
headers.put("Authorization", "Bearer " + smartsheet.getAccessToken());
headers.put(HEADER_CONTENT_TYPE, JSON_CONTENT_TYPE);
// Set assumed user
if (smartsheet.getAssumedUser() != null) {
headers.put("Assume-User", URLEncoder.encode(smartsheet.getAssumedUser(), StandardCharsets.UTF_8));
}
if (smartsheet.getChangeAgent() != null) {
headers.put("Smartsheet-Change-Agent", URLEncoder.encode(smartsheet.getChangeAgent(), StandardCharsets.UTF_8));
}
if (smartsheet.getUserAgent() != null) {
headers.put("User-Agent", smartsheet.getUserAgent());
}
return headers;
}
int getResponseLogLength() {
// not cached to allow for it to be changed dynamically by client code
return Integer.getInteger(PROPERTY_RESPONSE_LOG_CHARS, 1024);
}
}