Java tutorial
/** * Copyright (C) 2013 Brightcove Inc. All Rights Reserved. No use, copying or distribution of this * work may be made except in accordance with a valid license agreement from Brightcove Inc. This * notice must be included on all copies, modifications and derivatives of this work. * * Brightcove Inc MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE SOFTWARE, * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. BRIGHTCOVE SHALL NOT BE * LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS * SOFTWARE OR ITS DERIVATIVES. * * "Brightcove" is a registered trademark of Brightcove Inc. */ package com.brightcove.zencoder.client; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.List; import org.codehaus.jackson.map.DeserializationConfig; import org.codehaus.jackson.map.ObjectMapper; import org.codehaus.jackson.map.PropertyNamingStrategy; import org.codehaus.jackson.map.SerializationConfig; import org.codehaus.jackson.map.annotate.JsonSerialize; import org.codehaus.jackson.map.type.TypeFactory; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.ResponseEntity; import org.springframework.web.client.HttpClientErrorException; import org.springframework.web.client.RestTemplate; import com.brightcove.zencoder.client.account.ZencoderAccount; import com.brightcove.zencoder.client.account.ZencoderAccountDetails; import com.brightcove.zencoder.client.reports.ZencoderAllUsage; import com.brightcove.zencoder.client.reports.ZencoderDate; import com.brightcove.zencoder.client.reports.ZencoderLiveUsage; import com.brightcove.zencoder.client.reports.ZencoderVodUsage; import com.brightcove.zencoder.client.request.ZencoderCreateJobRequest; import com.brightcove.zencoder.client.response.ZencoderCreateJobResponse; import com.brightcove.zencoder.client.response.ZencoderInputOutputProgress; import com.brightcove.zencoder.client.response.ZencoderJobDetail; import com.brightcove.zencoder.client.response.ZencoderJobDetailResponse; import com.brightcove.zencoder.client.response.ZencoderJobProgress; import com.brightcove.zencoder.client.response.ZencoderMediaFile; public class ZencoderClient { public static final String API_URL = "https://app.zencoder.com/api/v2"; private String api_key; private String api_url; private RestTemplate rt; private ObjectMapper mapper; public ZencoderClient(String api_key) { this.api_key = api_key; this.api_url = API_URL; this.rt = new RestTemplate(); this.mapper = createObjectMapper(); } /** * Abstracted out for easier testing. */ @SuppressWarnings("deprecation") protected ObjectMapper createObjectMapper() { ObjectMapper m = new ObjectMapper(); m.configure(SerializationConfig.Feature.WRITE_NULL_PROPERTIES, false); m.configure(SerializationConfig.Feature.WRITE_ENUMS_USING_TO_STRING, true); m.configure(DeserializationConfig.Feature.READ_ENUMS_USING_TO_STRING, true); m.setPropertyNamingStrategy(PropertyNamingStrategy.CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES); m.setSerializationInclusion(JsonSerialize.Inclusion.NON_EMPTY); // If Zencoder adds a new field before we have a chance to update, silently ignore these fields. // NOTE: disable this during testing m.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false); return m; } public String getApiKey() { return api_key; } public void setApiKey(String api_key) { this.api_key = api_key; } public String getApiUrl() { return api_url; } public void setApiUrl(String api_url) { this.api_url = api_url; } public RestTemplate getRestTemplate() { return rt; } public void setRestTemplate(RestTemplate rt) { this.rt = rt; } private HttpHeaders getHeaders() { HttpHeaders headers = new HttpHeaders(); headers.add("Accept", "application/json"); headers.add("Content-Type", "application/json; charset=utf-8"); headers.add("Zencoder-Api-Key", api_key); headers.add("User-Agent", "zencoder-java-2.0"); return headers; } /** * Creates a VOD transcode job. * * @see https://app.zencoder.com/docs/api/jobs/create * @param job * @return ZencoderJobResponse * @throws ZencoderClientException */ public ZencoderCreateJobResponse createZencoderJob(ZencoderCreateJobRequest job) throws ZencoderClientException { String url = api_url + "/jobs"; String body = null; try { body = mapper.writeValueAsString(job); } catch (Exception e) { throw new ZencoderClientException("Unable to serialize ZencoderCreateJobRequest as JSON", e); } HttpHeaders headers = getHeaders(); @SuppressWarnings("rawtypes") HttpEntity entity = new HttpEntity<String>(body, headers); ResponseEntity<String> response = null; try { response = rt.exchange(url, HttpMethod.POST, entity, String.class, new HashMap<String, Object>()); } catch (HttpClientErrorException hcee) { throw new ZencoderClientException(hcee.getResponseBodyAsString(), hcee); } ZencoderCreateJobResponse zencoderJobResponse = null; try { zencoderJobResponse = mapper.readValue(response.getBody(), ZencoderCreateJobResponse.class); } catch (Exception e) { throw new ZencoderClientException("Unable to deserialize ZencoderCreateJobResponse as JSON", e); } return zencoderJobResponse; } /** * Lists the most recent jobs created (up to 50) * * @return A list of jobs. * @throws ZencoderClientException */ public List<ZencoderJobDetail> listJobs() throws ZencoderClientException { return listJobs(1, 50); } /** * Lists jobs with pagination. * * @param page Which page to return * @param per_page How many jobs per page to return * @return A list of jobs. * @throws ZencoderClientException */ public List<ZencoderJobDetail> listJobs(Integer page, Integer per_page) throws ZencoderClientException { String url = api_url + "/jobs"; if (page != null || per_page != null) { if (page == null) { page = 1; } if (per_page == null) { per_page = 50; } url = url + "?page=" + page + "&per_page=" + per_page; } HttpHeaders headers = getHeaders(); @SuppressWarnings("rawtypes") HttpEntity entity = new HttpEntity<String>("", headers); ResponseEntity<String> response = null; try { response = rt.exchange(url, HttpMethod.GET, entity, String.class, new HashMap<String, Object>()); } catch (HttpClientErrorException hcee) { throw new ZencoderClientException(hcee.getResponseBodyAsString(), hcee); } List<ZencoderJobDetailResponse> jobs = null; try { TypeFactory typeFactory = TypeFactory.defaultInstance(); jobs = mapper.readValue(response.getBody(), typeFactory.constructCollectionType(List.class, ZencoderJobDetailResponse.class)); } catch (Exception e) { throw new ZencoderClientException("Unable to deserialize ZencoderCreateJobResponse as JSON", e); } List<ZencoderJobDetail> job_details = new ArrayList<ZencoderJobDetail>(); for (ZencoderJobDetailResponse job : jobs) { job_details.add(job.getJob()); } return job_details; } /** * Gets details about an existing VOD transcode job. * * @see https://app.zencoder.com/docs/api/jobs/show * @param id * @return * @throws ZencoderClientException */ public ZencoderJobDetail getZencoderJob(String id) throws ZencoderClientException { String url = api_url + "/jobs/" + id + ".json"; HttpHeaders headers = getHeaders(); @SuppressWarnings("rawtypes") HttpEntity entity = new HttpEntity<String>("", headers); ResponseEntity<String> response = null; try { response = rt.exchange(url, HttpMethod.GET, entity, String.class, new HashMap<String, Object>()); } catch (HttpClientErrorException hcee) { throw new ZencoderClientException(hcee.getResponseBodyAsString(), hcee); } ZencoderJobDetailResponse job_details = null; try { job_details = mapper.readValue(response.getBody(), ZencoderJobDetailResponse.class); } catch (Exception e) { throw new ZencoderClientException("Unable to deserialize ZencoderCreateJobResponse as JSON", e); } return job_details.getJob(); } /** * Gets progress information about an existing VOD transcode job. * * @see https://app.zencoder.com/docs/api/jobs/progress * @param id * @return * @throws ZencoderClientException */ public ZencoderJobProgress getJobProgress(String id) throws ZencoderClientException { String url = api_url + "/jobs/" + id + "/progress.json"; HttpHeaders headers = getHeaders(); @SuppressWarnings("rawtypes") HttpEntity entity = new HttpEntity<String>("", headers); ResponseEntity<String> response = null; try { response = rt.exchange(url, HttpMethod.GET, entity, String.class, new HashMap<String, Object>()); } catch (HttpClientErrorException hcee) { throw new ZencoderClientException(hcee.getResponseBodyAsString(), hcee); } ZencoderJobProgress job_progress = null; try { job_progress = mapper.readValue(response.getBody(), ZencoderJobProgress.class); } catch (Exception e) { throw new ZencoderClientException("Unable to deserialize ZencoderCreateJobResponse as JSON", e); } return job_progress; } /** * Gets progress information about an existing VOD transcode input. * * @see https://app.zencoder.com/docs/api/inputs/progress * @param id * @return * @throws ZencoderClientException */ public ZencoderInputOutputProgress getInputProgress(String id) throws ZencoderClientException { String url = api_url + "/inputs/" + id + "/progress.json"; HttpHeaders headers = getHeaders(); @SuppressWarnings("rawtypes") HttpEntity entity = new HttpEntity<String>("", headers); ResponseEntity<String> response = null; try { response = rt.exchange(url, HttpMethod.GET, entity, String.class, new HashMap<String, Object>()); } catch (HttpClientErrorException hcee) { throw new ZencoderClientException(hcee.getResponseBodyAsString(), hcee); } ZencoderInputOutputProgress input_progress = null; try { input_progress = mapper.readValue(response.getBody(), ZencoderInputOutputProgress.class); } catch (Exception e) { throw new ZencoderClientException("Unable to deserialize ZencoderInputOutputProgress as JSON", e); } return input_progress; } /** * Gets progress information about an existing VOD transcode output. * * @see https://app.zencoder.com/docs/api/outputs/progress * @param id * @return * @throws ZencoderClientException */ public ZencoderInputOutputProgress getOutputProgress(String id) throws ZencoderClientException { String url = api_url + "/outputs/" + id + "/progress.json"; HttpHeaders headers = getHeaders(); @SuppressWarnings("rawtypes") HttpEntity entity = new HttpEntity<String>("", headers); ResponseEntity<String> response = null; try { response = rt.exchange(url, HttpMethod.GET, entity, String.class, new HashMap<String, Object>()); } catch (HttpClientErrorException hcee) { throw new ZencoderClientException(hcee.getResponseBodyAsString(), hcee); } ZencoderInputOutputProgress output_progress = null; try { output_progress = mapper.readValue(response.getBody(), ZencoderInputOutputProgress.class); } catch (Exception e) { throw new ZencoderClientException("Unable to deserialize ZencoderInputOutputProgress as JSON", e); } return output_progress; } /** * Gets the details of a given input. * * @param id * @return * @throws ZencoderClientException */ public ZencoderMediaFile getInputDetails(String id) throws ZencoderClientException { String url = api_url + "/inputs/" + id + ".json"; HttpHeaders headers = getHeaders(); @SuppressWarnings("rawtypes") HttpEntity entity = new HttpEntity<String>("", headers); ResponseEntity<String> response = null; try { response = rt.exchange(url, HttpMethod.GET, entity, String.class, new HashMap<String, Object>()); } catch (HttpClientErrorException hcee) { throw new ZencoderClientException(hcee.getResponseBodyAsString(), hcee); } ZencoderMediaFile input_details = null; try { input_details = mapper.readValue(response.getBody(), ZencoderMediaFile.class); } catch (Exception e) { throw new ZencoderClientException("Unable to deserialize ZencoderMediaFile as JSON", e); } return input_details; } /** * Gets the details of a given output. * * @see https://app.zencoder.com/docs/api/outputs/show * @param id * @return * @throws ZencoderClientException */ public ZencoderMediaFile getOutputDetails(String id) throws ZencoderClientException { String url = api_url + "/outputs/" + id + ".json"; HttpHeaders headers = getHeaders(); @SuppressWarnings("rawtypes") HttpEntity entity = new HttpEntity<String>("", headers); ResponseEntity<String> response = null; try { response = rt.exchange(url, HttpMethod.GET, entity, String.class, new HashMap<String, Object>()); } catch (HttpClientErrorException hcee) { throw new ZencoderClientException(hcee.getResponseBodyAsString(), hcee); } ZencoderMediaFile output_details = null; try { output_details = mapper.readValue(response.getBody(), ZencoderMediaFile.class); } catch (Exception e) { throw new ZencoderClientException("Unable to deserialize ZencoderMediaFile as JSON", e); } return output_details; } /** * If a job has failed processing you may request that it be attempted again. * * @see https://app.zencoder.com/docs/api/jobs/resubmit * @param id * @throws ZencoderClientException */ public void resubmitJob(String id) throws ZencoderClientException { String url = api_url + "/jobs/" + id + "/resubmit.json"; HttpHeaders headers = getHeaders(); @SuppressWarnings("rawtypes") HttpEntity entity = new HttpEntity<String>("", headers); try { rt.exchange(url, HttpMethod.PUT, entity, String.class, new HashMap<String, Object>()); } catch (HttpClientErrorException hcee) { throw new ZencoderClientException(hcee.getResponseBodyAsString(), hcee); } } /** * If you wish to cancel a job that has not yet finished processing. * * @see https://app.zencoder.com/docs/api/jobs/cancel * @param id * @throws ZencoderClientException */ public void cancelJob(String id) throws ZencoderClientException { String url = api_url + "/jobs/" + id + "/cancel.json"; HttpHeaders headers = getHeaders(); @SuppressWarnings("rawtypes") HttpEntity entity = new HttpEntity<String>("", headers); try { rt.exchange(url, HttpMethod.PUT, entity, String.class, new HashMap<String, Object>()); } catch (HttpClientErrorException hcee) { throw new ZencoderClientException(hcee.getResponseBodyAsString(), hcee); } } /** * Finishes the input on a Live streaming job. Has no effect on non-Live jobs. * * @see https://app.zencoder.com/docs/api/jobs/finish * @param id * @throws ZencoderClientException */ public void finishLiveJob(String id) throws ZencoderClientException { String url = api_url + "/jobs/" + id + "/finish"; HttpHeaders headers = getHeaders(); @SuppressWarnings("rawtypes") HttpEntity entity = new HttpEntity<String>("", headers); try { rt.exchange(url, HttpMethod.PUT, entity, String.class, new HashMap<String, Object>()); } catch (HttpClientErrorException hcee) { throw new ZencoderClientException(hcee.getResponseBodyAsString(), hcee); } } // Accounts API - https://app.zencoder.com/docs/api/accounts /** * Creates a Zencoder Account. * New accounts will be created under the Test (Free) plan. * NOTE: A password will be generated and returned if not specified. * * @see https://app.zencoder.com/docs/api/accounts/create * @see http://zencoder.com/en/terms * @param account The account to create. * @return The created account with it's API key and password. * @throws ZencoderClientException */ public ZencoderAccount createAccount(ZencoderAccount account) throws ZencoderClientException { String url = api_url + "/account"; String body = null; try { body = mapper.writeValueAsString(account); } catch (Exception e) { throw new ZencoderClientException("Unable to serialize ZencoderAccount as JSON", e); } HttpHeaders headers = getHeaders(); @SuppressWarnings("rawtypes") HttpEntity entity = new HttpEntity<String>(body, headers); ResponseEntity<String> response = null; try { response = rt.exchange(url, HttpMethod.POST, entity, String.class, new HashMap<String, Object>()); } catch (HttpClientErrorException hcee) { throw new ZencoderClientException(hcee.getResponseBodyAsString(), hcee); } ZencoderAccount zencoderAccountResponse = null; try { zencoderAccountResponse = mapper.readValue(response.getBody(), ZencoderAccount.class); } catch (Exception e) { throw new ZencoderClientException("Unable to deserialize ZencoderAccount as JSON", e); } return zencoderAccountResponse; } /** * Retrieve your Zencoder Account Details * * @see https://app.zencoder.com/docs/api/accounts/show * @return The status and billing details for this account. * @throws ZencoderClientException */ public ZencoderAccountDetails getAccountDetails() throws ZencoderClientException { String url = api_url + "/account"; HttpHeaders headers = getHeaders(); @SuppressWarnings("rawtypes") HttpEntity entity = new HttpEntity<String>("", headers); ResponseEntity<String> response = null; try { response = rt.exchange(url, HttpMethod.GET, entity, String.class, new HashMap<String, Object>()); } catch (HttpClientErrorException hcee) { throw new ZencoderClientException(hcee.getResponseBodyAsString(), hcee); } ZencoderAccountDetails account_details = null; try { account_details = mapper.readValue(response.getBody(), ZencoderAccountDetails.class); } catch (Exception e) { throw new ZencoderClientException("Unable to deserialize ZencoderAccountDetails as JSON", e); } return account_details; } /** * Sets whether or not your account should be in the limited integration mode. * Use 'true' to make your account limited to integration mode. * Use 'false' to make your account a regular account. * * @see https://app.zencoder.com/docs/api/accounts/integration * @param integration_mode Integration Mode setting. * @throws ZencoderClientException */ public void setAccountIntegrationMode(boolean integration_mode) throws ZencoderClientException { String url = null; if (integration_mode) { url = api_url + "/account/integration"; } else { url = api_url + "/account/live"; } HttpHeaders headers = getHeaders(); @SuppressWarnings("rawtypes") HttpEntity entity = new HttpEntity<String>("", headers); try { rt.exchange(url, HttpMethod.PUT, entity, String.class, new HashMap<String, Object>()); } catch (HttpClientErrorException hcee) { throw new ZencoderClientException(hcee.getResponseBodyAsString(), hcee); } } // Reports API - https://app.zencoder.com/docs/api/reports /** * The VOD usage for the specified time period. * * NOTE: It's important to note that our service operates in the UTC time zone * (including billing periods). All dates and times reported will be in UTC. * * @see https://app.zencoder.com/docs/api/reports/vod * @see https://app.zencoder.com/docs/api/encoding/job/grouping * @param from * (optional) Start date (default: 30 days ago). * @param to * (optional) End date (default: yesterday). * @param grouping * (optional) Minute usage for only one report grouping (default: none). * @return The VOD usage for the specified time period. * @throws ZencoderClientException */ public ZencoderVodUsage getUsageForVod(Date from, Date to, String grouping) throws ZencoderClientException { String url = api_url + "/reports/vod" + createUsageQueryArgString(from, to, grouping); HttpHeaders headers = getHeaders(); @SuppressWarnings("rawtypes") HttpEntity entity = new HttpEntity<String>("", headers); ResponseEntity<String> response = null; try { response = rt.exchange(url, HttpMethod.GET, entity, String.class, new HashMap<String, Object>()); } catch (HttpClientErrorException hcee) { throw new ZencoderClientException(hcee.getResponseBodyAsString(), hcee); } ZencoderVodUsage usage = null; try { usage = mapper.readValue(response.getBody(), ZencoderVodUsage.class); } catch (Exception e) { throw new ZencoderClientException("Unable to deserialize ZencoderVodUsage as JSON", e); } return usage; } /** * The Live usage for the specified time period. * * NOTE: It's important to note that our service operates in the UTC time zone * (including billing periods). All dates and times reported will be in UTC. * * @see https://app.zencoder.com/docs/api/reports/live * @see https://app.zencoder.com/docs/api/encoding/job/grouping * @param from * (optional) Start date (default: 30 days ago). * @param to * (optional) End date (default: yesterday). * @param grouping * (optional) Minute usage for only one report grouping (default: none). * @return The Live usage for the specified time period. * @throws ZencoderClientException */ public ZencoderLiveUsage getUsageForLive(Date from, Date to, String grouping) throws ZencoderClientException { String url = api_url + "/reports/live" + createUsageQueryArgString(from, to, grouping); HttpHeaders headers = getHeaders(); @SuppressWarnings("rawtypes") HttpEntity entity = new HttpEntity<String>("", headers); ResponseEntity<String> response = null; try { response = rt.exchange(url, HttpMethod.GET, entity, String.class, new HashMap<String, Object>()); } catch (HttpClientErrorException hcee) { throw new ZencoderClientException(hcee.getResponseBodyAsString(), hcee); } ZencoderLiveUsage usage = null; try { usage = mapper.readValue(response.getBody(), ZencoderLiveUsage.class); } catch (Exception e) { throw new ZencoderClientException("Unable to deserialize ZencoderLiveUsage as JSON", e); } return usage; } /** * The VOD+Live usage for the specified time period. * * NOTE: It's important to note that our service operates in the UTC time zone * (including billing periods). All dates and times reported will be in UTC. * * @see https://app.zencoder.com/docs/api/reports/all * @see https://app.zencoder.com/docs/api/encoding/job/grouping * @param from * (optional) Start date (default: 30 days ago). * @param to * (optional) End date (default: yesterday). * @param grouping * (optional) Minute usage for only one report grouping (default: none). * @return The VOD+Live usage for the specified time period. * @throws ZencoderClientException */ public ZencoderAllUsage getUsageForVodAndLive(Date from, Date to, String grouping) throws ZencoderClientException { String url = api_url + "/reports/all" + createUsageQueryArgString(from, to, grouping); HttpHeaders headers = getHeaders(); @SuppressWarnings("rawtypes") HttpEntity entity = new HttpEntity<String>("", headers); ResponseEntity<String> response = null; try { response = rt.exchange(url, HttpMethod.GET, entity, String.class, new HashMap<String, Object>()); } catch (HttpClientErrorException hcee) { throw new ZencoderClientException(hcee.getResponseBodyAsString(), hcee); } ZencoderAllUsage usage = null; try { usage = mapper.readValue(response.getBody(), ZencoderAllUsage.class); } catch (Exception e) { throw new ZencoderClientException("Unable to deserialize ZencoderLiveUsage as JSON", e); } return usage; } /** * Helper method to generate URL query args String. * TODO: refactor this to use some query args library. */ private String createUsageQueryArgString(Date from, Date to, String grouping) { String query = ""; if (from != null || to != null || grouping != null) { query += "?"; } if (from != null) { query += "from=" + ZencoderDate.toZC(from); if (to != null || grouping != null) { query += "&"; } } if (to != null) { query += "to=" + ZencoderDate.toZC(to); if (grouping != null) { query += "&"; } } if (grouping != null) { query += "grouping=" + grouping; } return query; } }