/******************************************************************************
* Copyright (c) 2011 GitHub Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Kevin Sawicki (GitHub Inc.) - initial API and implementation
*****************************************************************************/
package org.eclipse.egit.github.core.service;
import static java.net.HttpURLConnection.HTTP_CREATED;
import static org.eclipse.egit.github.core.client.IGitHubConstants.SEGMENT_DOWNLOADS;
import static org.eclipse.egit.github.core.client.IGitHubConstants.SEGMENT_REPOS;
import static org.eclipse.egit.github.core.client.PagedRequest.PAGE_FIRST;
import static org.eclipse.egit.github.core.client.PagedRequest.PAGE_SIZE;
import com.google.gson.reflect.TypeToken;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.egit.github.core.Download;
import org.eclipse.egit.github.core.DownloadResource;
import org.eclipse.egit.github.core.IRepositoryIdProvider;
import org.eclipse.egit.github.core.client.GitHubClient;
import org.eclipse.egit.github.core.client.GitHubRequest;
import org.eclipse.egit.github.core.client.PageIterator;
import org.eclipse.egit.github.core.client.PagedRequest;
import org.eclipse.egit.github.core.util.MultiPartUtils;
/**
* Service for accessing, creating, and deleting repositories downloads.
*
* @see <a href="http://developer.github.com/v3/repos/downloads">GitHub
* downloads API documentation</a>
*/
public class DownloadService extends GitHubService {
/**
* UPLOAD_KEY
*/
public static final String UPLOAD_KEY = "key"; //$NON-NLS-1$
/**
* UPLOAD_ACL
*/
public static final String UPLOAD_ACL = "acl"; //$NON-NLS-1$
/**
* UPLOAD_SUCCESS_ACTION_STATUS
*/
public static final String UPLOAD_SUCCESS_ACTION_STATUS = "success_action_status"; //$NON-NLS-1$
/**
* UPLOAD_FILENAME
*/
public static final String UPLOAD_FILENAME = "Filename"; //$NON-NLS-1$
/**
* UPLOAD_AWS_ACCESS_KEY_ID
*/
public static final String UPLOAD_AWS_ACCESS_KEY_ID = "AWSAccessKeyId"; //$NON-NLS-1$
/**
* UPLOAD_POLICY
*/
public static final String UPLOAD_POLICY = "Policy"; //$NON-NLS-1$
/**
* UPLOAD_SIGNATURE
*/
public static final String UPLOAD_SIGNATURE = "Signature"; //$NON-NLS-1$
/**
* UPLOAD_FILE
*/
public static final String UPLOAD_FILE = "file"; //$NON-NLS-1$
/**
* UPLOAD_CONTENT_TYPE
*/
public static final String UPLOAD_CONTENT_TYPE = "Content-Type"; //$NON-NLS-1$
/**
* Create download service
*/
public DownloadService() {
super();
}
/**
* Create download service
*
* @param client
*/
public DownloadService(GitHubClient client) {
super(client);
}
/**
* Get download metadata for given repository and id
*
* @param repository
* @param id
* @return download
* @throws IOException
*/
public Download getDownload(IRepositoryIdProvider repository, int id)
throws IOException {
final String repoId = getId(repository);
StringBuilder uri = new StringBuilder(SEGMENT_REPOS);
uri.append('/').append(repoId);
uri.append(SEGMENT_DOWNLOADS);
uri.append('/').append(id);
GitHubRequest request = createRequest();
request.setUri(uri);
request.setType(Download.class);
return (Download) client.get(request).getBody();
}
/**
* Create paged downloads request
*
* @param repository
* @param start
* @param size
* @return request
*/
protected PagedRequest<Download> createDownloadsRequest(
IRepositoryIdProvider repository, int start, int size) {
final String repoId = getId(repository);
StringBuilder uri = new StringBuilder(SEGMENT_REPOS);
uri.append('/').append(repoId);
uri.append(SEGMENT_DOWNLOADS);
PagedRequest<Download> request = createPagedRequest(start, size);
request.setType(new TypeToken<List<Download>>() {
}.getType());
request.setUri(uri);
return request;
}
/**
* Get metadata for all downloads for given repository
*
* @param repository
* @return non-null but possibly empty list of download metadata
* @throws IOException
*/
public List<Download> getDownloads(IRepositoryIdProvider repository)
throws IOException {
return getAll(pageDownloads(repository));
}
/**
* Page metadata for downloads for given repository
*
* @param repository
* @return iterator over pages of downloads
*/
public PageIterator<Download> pageDownloads(IRepositoryIdProvider repository) {
return pageDownloads(repository, PAGE_SIZE);
}
/**
* Page downloads for given repository
*
* @param repository
* @param size
* @return iterator over pages of downloads
*/
public PageIterator<Download> pageDownloads(
IRepositoryIdProvider repository, int size) {
return pageDownloads(repository, PAGE_FIRST, size);
}
/**
* Page downloads for given repository
*
* @param repository
* @param start
* @param size
* @return iterator over pages of downloads
*/
public PageIterator<Download> pageDownloads(
IRepositoryIdProvider repository, int start, int size) {
PagedRequest<Download> request = createDownloadsRequest(repository,
start, size);
return createPageIterator(request);
}
/**
* Delete download with given id from given repository
*
* @param repository
* @param id
* @throws IOException
*/
public void deleteDownload(IRepositoryIdProvider repository, int id)
throws IOException {
final String repoId = getId(repository);
StringBuilder uri = new StringBuilder(SEGMENT_REPOS);
uri.append('/').append(repoId);
uri.append(SEGMENT_DOWNLOADS);
uri.append('/').append(id);
client.delete(uri.toString());
}
/**
* Create a new resource for download associated with the given repository
*
* @param repository
* @param download
* @return download resource
* @throws IOException
*/
public DownloadResource createResource(IRepositoryIdProvider repository,
Download download) throws IOException {
final String repoId = getId(repository);
StringBuilder uri = new StringBuilder(SEGMENT_REPOS);
uri.append('/').append(repoId);
uri.append(SEGMENT_DOWNLOADS);
return client.post(uri.toString(), download, DownloadResource.class);
}
/**
* Upload a resource to be available as the download described by the given
* resource.
*
* @param resource
* @param content
* @param size
* @throws IOException
*/
public void uploadResource(DownloadResource resource, InputStream content,
long size) throws IOException {
if (resource == null)
throw new IllegalArgumentException(
"Download resource cannot be null"); //$NON-NLS-1$
if (content == null)
throw new IllegalArgumentException(
"Content input stream cannot be null"); //$NON-NLS-1$
Map<String, Object> parts = new LinkedHashMap<String, Object>();
parts.put(UPLOAD_KEY, resource.getPath());
parts.put(UPLOAD_ACL, resource.getAcl());
parts.put(UPLOAD_SUCCESS_ACTION_STATUS, Integer.toString(HTTP_CREATED));
parts.put(UPLOAD_FILENAME, resource.getName());
parts.put(UPLOAD_AWS_ACCESS_KEY_ID, resource.getAccesskeyid());
parts.put(UPLOAD_POLICY, resource.getPolicy());
parts.put(UPLOAD_SIGNATURE, resource.getSignature());
parts.put(UPLOAD_CONTENT_TYPE, resource.getMimeType());
parts.put(UPLOAD_FILE, content);
HttpURLConnection connection = MultiPartUtils.post(resource.getS3Url(),
parts);
int status = connection.getResponseCode();
if (status != HTTP_CREATED)
throw new IOException("Unexpected response status of " + status); //$NON-NLS-1$
}
/**
* Create download and set the content to be the content of given input
* stream. This is a convenience method that performs a
* {@link #createResource(IRepositoryIdProvider, Download)} followed by a
* {@link #uploadResource(DownloadResource, InputStream, long)} with the
* results.
*
* @param repository
* @param download
* metadata about the download
* @param content
* raw content of the download
* @param size
* size of content in the input stream
* @return created resource
* @throws IOException
*/
public DownloadResource createDownload(IRepositoryIdProvider repository,
Download download, InputStream content, long size)
throws IOException {
DownloadResource resource = createResource(repository, download);
uploadResource(resource, content, size);
return resource;
}
/**
* Create download from content of given file.
*
* @see #createDownload(IRepositoryIdProvider, Download, InputStream, long)
* @param repository
* @param download
* metadata about the download
* @param file
* must be non-null
* @return created resource
* @throws IOException
*/
public DownloadResource createDownload(IRepositoryIdProvider repository,
Download download, File file) throws IOException {
if (file == null)
throw new IllegalArgumentException("File cannot be null"); //$NON-NLS-1$
return createDownload(repository, download, new FileInputStream(file),
file.length());
}
}