package com.uploadcare.api; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.PropertyNamingStrategy; import com.uploadcare.data.CopyFileData; import com.uploadcare.data.FileData; import com.uploadcare.data.ProjectData; import com.uploadcare.exceptions.UploadcareApiException; import com.uploadcare.urls.Urls; import org.apache.http.NameValuePair; import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.methods.HttpDelete; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; import org.apache.http.message.BasicNameValuePair; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.net.URI; import java.util.ArrayList; import java.util.List; /** * Uploadcare API client. * * Provides simple access to {@code File} and {@code Project} resources. * * @see com.uploadcare.api.File * @see Project */ public class Client { private final String publicKey; private final String privateKey; private final boolean simpleAuth; private final CloseableHttpClient httpClient; private final ObjectMapper objectMapper; private final RequestHelperProvider requestHelperProvider; /** * Initializes a client with custom access keys and simple authentication. * * @param publicKey Public key * @param privateKey Private key */ public Client(String publicKey, String privateKey) { this(publicKey, privateKey, true, null); } /** * Initializes a client with custom access keys and simple authentication. * * @param publicKey Public key * @param privateKey Private key * @param privateKey CloseableHttpClient */ public Client(String publicKey, String privateKey, CloseableHttpClient httpClient) { this(publicKey, privateKey, true, null, httpClient); } /** * Initializes a client with custom access keys. * Can use simple or secure authentication. * * @param publicKey Public key * @param privateKey Private key * @param simpleAuth If {@code false}, HMAC-based authentication is used * @param requestHelperProvider Should be {@code null} to use {@link DefaultRequestHelperProvider} */ public Client( String publicKey, String privateKey, boolean simpleAuth, RequestHelperProvider requestHelperProvider) { this(publicKey, privateKey, simpleAuth, requestHelperProvider, null); } /** * Initializes a client with custom access keys. * Can use simple or secure authentication. * * @param publicKey Public key * @param privateKey Private key * @param simpleAuth If {@code false}, HMAC-based authentication is used * @param requestHelperProvider Should be {@code null} to use {@link DefaultRequestHelperProvider} * @param httpClient Custom HttpClient */ public Client( String publicKey, String privateKey, boolean simpleAuth, RequestHelperProvider requestHelperProvider, CloseableHttpClient httpClient) { this.publicKey = publicKey; this.privateKey = privateKey; this.simpleAuth = simpleAuth; if (requestHelperProvider != null) { this.requestHelperProvider = requestHelperProvider; this.httpClient = null; this.objectMapper = null; } else { this.requestHelperProvider = new DefaultRequestHelperProvider(); if (httpClient != null) { this.httpClient = httpClient; } else { PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(); cm.setMaxTotal(200); cm.setDefaultMaxPerRoute(20); this.httpClient = HttpClients.custom() .setConnectionManager(cm) .build(); } this.objectMapper = new ObjectMapper(); this.objectMapper.setPropertyNamingStrategy(PropertyNamingStrategy.CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES); this.objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); } } /** * Creates a client with demo credentials. * Useful for tests and anonymous access. * * <b>Warning!</b> Do not use in production. * All demo account files are eventually purged. * * @return A demo client */ public static Client demoClient() { return new Client("demopublickey", "demoprivatekey"); } /** * Returns the public key. * * @return Public key */ public String getPublicKey() { return publicKey; } /** * Returns the private key. * * @return Private key */ public String getPrivateKey() { return privateKey; } /** * Returns {@code true}, if simple authentication is used. * * @return {@code true}, if simple authentication is used, {@code false} otherwise */ public boolean isSimpleAuth() { return simpleAuth; } CloseableHttpClient getHttpClient() { return httpClient; } ObjectMapper getObjectMapper() { return objectMapper; } public RequestHelper getRequestHelper() { return requestHelperProvider.get(this); } /** * Requests project info from the API. * * @return Project resource */ public Project getProject() { URI url = Urls.apiProject(); RequestHelper requestHelper = getRequestHelper(); ProjectData projectData = requestHelper.executeQuery(new HttpGet(url), true, ProjectData.class); return new Project(this, projectData); } /** * Requests file data. * * @param fileId Resource UUID * @return File resource */ public File getFile(String fileId) { URI url = Urls.apiFile(fileId); RequestHelper requestHelper = getRequestHelper(); FileData fileData = requestHelper.executeQuery(new HttpGet(url), true, FileData.class); return new File(this, fileData); } /** * Begins to build a request for uploaded files for the current account. * * @return File resource request builder */ public FilesQueryBuilder getFiles() { return new FilesQueryBuilder(this); } /** * Marks a file as deleted. * * @param fileId Resource UUID */ public void deleteFile(String fileId) { URI url = Urls.apiFile(fileId); RequestHelper requestHelper = getRequestHelper(); requestHelper.executeCommand(new HttpDelete(url), true); } /** * Marks a file as saved. * * This has to be done for all files you want to keep. * Unsaved files are eventually purged. * * @param fileId Resource UUID */ public void saveFile(String fileId) { URI url = Urls.apiFileStorage(fileId); RequestHelper requestHelper = getRequestHelper(); requestHelper.executeCommand(new HttpPost(url), true); } /** * Closes client. * * Ensures that all connections kept alive by the manager get closed and system resources * allocated by those connections are released. */ public void close() { if (httpClient != null) { try { httpClient.close(); } catch (IOException e) { throw new UploadcareApiException("Error during closing CloseableHttpClient", e); } } } /** * @param fileId Resource UUID * @param storage Target storage name * @return An object containing the results of the copy request */ public CopyFileData copyFile(String fileId, String storage) { RequestHelper requestHelper = getRequestHelper(); HttpPost request = new HttpPost(Urls.apiFiles()); List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(); nameValuePairs.add(new BasicNameValuePair("source", fileId)); if (storage != null && !storage.isEmpty()) { nameValuePairs.add(new BasicNameValuePair("target", storage)); } try { request.setEntity(new UrlEncodedFormEntity(nameValuePairs)); } catch (UnsupportedEncodingException e) { throw new UploadcareApiException("Error during copyFile request creation", e); } return requestHelper.executeQuery(request, true, CopyFileData.class); } }