package weiboclient4j; import org.codehaus.jackson.annotate.JsonIgnoreProperties; import org.codehaus.jackson.type.TypeReference; import org.scribe.model.OAuthRequest; import org.scribe.model.Response; import org.scribe.model.Verb; import weiboclient4j.model.Url; import weiboclient4j.model.UrlInfo; import weiboclient4j.oauth2.SinaWeibo2AccessToken; import weiboclient4j.params.Paging; import weiboclient4j.params.ParameterAction; import weiboclient4j.params.Parameters; import static weiboclient4j.utils.JsonUtils.parseJsonObject; import weiboclient4j.utils.StreamUtils; import static weiboclient4j.utils.StreamUtils.closeQuietly; import static weiboclient4j.utils.StreamUtils.newStreamWriter; import weiboclient4j.utils.StringUtils; import static weiboclient4j.utils.StringUtils.isNotBlank; import java.io.BufferedOutputStream; import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; import java.io.File; import java.io.IOException; import java.io.OutputStream; import java.net.URL; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.TimeUnit; /** * @author Hover Ruan */ public class AbstractService { public static final String API2_URL = "https://api.weibo.com/2/"; protected static final TypeReference<List<Map<String, String>>> LIST_MAP_S_S_TYPE_REFERENCE = new TypeReference<List<Map<String, String>>>() { }; protected static final TypeReference<List<TagActionResponse>> TYPE_TAG_ACTION_RESPONSE_LIST = new TypeReference<List<TagActionResponse>>() { }; protected static final TypeReference<List<LongIdStringValue>> TYPE_LONG_ID_STRING_VALUE_LIST = new TypeReference<List<LongIdStringValue>>() { }; private static final int DEFAULT_TIMEOUT = 30; private WeiboClient client; private SinaWeibo2AccessToken accessToken; private int connectTimeoutDuration = DEFAULT_TIMEOUT; private TimeUnit connectTimeoutUnit = TimeUnit.SECONDS; private int readTimeoutDuration = DEFAULT_TIMEOUT; private TimeUnit readTimeoutUnit = TimeUnit.SECONDS; public AbstractService(WeiboClient client) { this.client = client; client.initService(this); } public static Parameters withParams(ParameterAction... actions) { return Parameters.create().addAll(actions); } public static Parameters buildParams(ParameterAction[] optionalParams, ParameterAction... requireParams) { return Parameters.create().addAll(optionalParams).addAll(requireParams); } protected static void buildUploadRequest(OAuthRequest request, String fileParamName, File file, Parameters params) throws IOException { ByteArrayOutputStream baos = null; OutputStream os = null; DataOutputStream dos = null; try { baos = new ByteArrayOutputStream(); os = new BufferedOutputStream(baos); dos = new DataOutputStream(os); StreamUtils.StreamWriter writer = newStreamWriter(dos); String boundary = "----weiboclient4j-upload" + System.currentTimeMillis(); request.addHeader("Content-Type", "multipart/form-data; boundary=" + boundary); boundary = "--" + boundary; writeFile(writer, boundary, fileParamName, file); writeParameters(writer, boundary, params); writer.writeLine(boundary + "--").writeLine(); dos.flush(); request.addPayload(baos.toByteArray()); } finally { closeQuietly(dos); closeQuietly(os); closeQuietly(baos); } } protected static void writeFile(StreamUtils.StreamWriter writer, String boundary, String fileParamName, File file) throws IOException { writer.writeLine(boundary) .writeLine(String.format("Content-Disposition: form-data; name=\"%s\"; filename=\"%s\"", fileParamName, file.getName())) .writeLine("Content-Type: " + getContentTypeFromImage(file)) .writeLine() .writeFile(file); } protected static void writeParameters(StreamUtils.StreamWriter writer, String boundary, Parameters params) throws IOException { for (Parameters.Parameter param : params.getParameterList()) { writer.writeLine(boundary) .writeLine("Content-Disposition: form-data; name=\"" + param.getKey() + "\"") .writeLine("Content-Type: text/plain; charset=" + StringUtils.DEFAULT_ENCODING) .writeLine() .writeLine(param.getValue().getBytes(StringUtils.DEFAULT_ENCODING)); } } protected static String getContentTypeFromImage(File imageFile) { String contentType = "image/jpeg"; String fileName = imageFile.getName(); if (isNotBlank(fileName)) { String lowerCaseFileName = fileName.toLowerCase(); if (lowerCaseFileName.endsWith(".gif")) { contentType = "image/gif"; } else if (lowerCaseFileName.endsWith(".png")) { contentType = "image/png"; } } return contentType; } public WeiboClient getClient() { return client; } public void setAccessToken(SinaWeibo2AccessToken accessToken) { this.accessToken = accessToken; } public void setConnectTimeoutDuration(int connectTimeoutDuration) { this.connectTimeoutDuration = connectTimeoutDuration; } public void setConnectTimeoutUnit(TimeUnit connectTimeoutUnit) { this.connectTimeoutUnit = connectTimeoutUnit; } public void setReadTimeoutDuration(int readTimeoutDuration) { this.readTimeoutDuration = readTimeoutDuration; } public void setReadTimeoutUnit(TimeUnit readTimeoutUnit) { this.readTimeoutUnit = readTimeoutUnit; } public <T> T doGet(String path, Paging paging, Parameters params, Class<T> clazz) throws WeiboClientException { return sendRequestAndGetResponseObject(createGetRequest(path), paging, params, clazz); } public <T> T doGet(String path, Parameters params, Class<T> clazz) throws WeiboClientException { return sendRequestAndGetResponseObject(createGetRequest(path), params, clazz); } public <T> T doGet(String path, Paging paging, Class<T> clazz) throws WeiboClientException { return sendRequestAndGetResponseObject(createGetRequest(path), paging, clazz); } public <T> T doGet(String path, Class<T> clazz) throws WeiboClientException { return sendRequestAndGetResponseObject(createGetRequest(path), clazz); } public <T> List<T> doGet(String path, TypeReference<List<T>> typeReference) throws WeiboClientException { return sendRequestAndGetResponseObject(createGetRequest(path), typeReference); } public <T> List<T> doGet(String path, Paging paging, TypeReference<List<T>> typeReference) throws WeiboClientException { return sendRequestAndGetResponseObject(createGetRequest(path), paging, typeReference); } public <T> List<T> doGet(String path, Parameters params, TypeReference<List<T>> typeReference) throws WeiboClientException { return sendRequestAndGetResponseObject(createGetRequest(path), params, typeReference); } public <T> List<T> doGet(String path, Paging paging, Parameters params, TypeReference<List<T>> typeReference) throws WeiboClientException { return sendRequestAndGetResponseObject(createGetRequest(path), paging, params, typeReference); } public <T> T doPost(String path, Paging paging, Parameters params, Class<T> clazz) throws WeiboClientException { return sendRequestAndGetResponseObject(createPostRequest(path), paging, params, clazz); } public <T> T doPost(String path, Parameters params, Class<T> clazz) throws WeiboClientException { return sendRequestAndGetResponseObject(createPostRequest(path), params, clazz); } public <T> T doPost(String path, Paging paging, Class<T> clazz) throws WeiboClientException { return sendRequestAndGetResponseObject(createPostRequest(path), paging, clazz); } public <T> T doPost(String path, Class<T> clazz) throws WeiboClientException { return sendRequestAndGetResponseObject(createPostRequest(path), clazz); } public <T> List<T> doPost(String path, Paging paging, Parameters params, TypeReference<List<T>> typeReference) throws WeiboClientException { return sendRequestAndGetResponseObject(createPostRequest(path), paging, params, typeReference); } public <T> List<T> doPost(String path, Parameters params, TypeReference<List<T>> typeReference) throws WeiboClientException { return sendRequestAndGetResponseObject(createPostRequest(path), params, typeReference); } public <T> List<T> doPost(String path, Paging paging, TypeReference<List<T>> typeReference) throws WeiboClientException { return sendRequestAndGetResponseObject(createPostRequest(path), paging, typeReference); } public <T> List<T> doPost(String path, TypeReference<List<T>> typeReference) throws WeiboClientException { return sendRequestAndGetResponseObject(createPostRequest(path), typeReference); } public <T> List<T> sendRequestAndGetResponseObject(OAuthRequest request, Parameters params, TypeReference<List<T>> typeReference) throws WeiboClientException { return sendRequestAndGetResponseObject(request, Paging.EMPTY, params, typeReference); } public <T> List<T> sendRequestAndGetResponseObject(OAuthRequest request, Paging paging, TypeReference<List<T>> typeReference) throws WeiboClientException { return sendRequestAndGetResponseObject(request, paging, Parameters.create(), typeReference); } public <T> List<T> sendRequestAndGetResponseObject(OAuthRequest request, Paging paging, Parameters params, TypeReference<List<T>> typeReference) throws WeiboClientException { if (paging != null) { params.add(paging); } params.appendTo(request); return sendRequestAndGetResponseObject(request, typeReference); } public <T> List<T> sendRequestAndGetResponseObject(OAuthRequest request, TypeReference<List<T>> typeReference) throws WeiboClientException { Response response = request.send(); return parseJsonObject(response, typeReference); } public <T> T sendRequestAndGetResponseObject(OAuthRequest request, Parameters params, Class<T> clazz) throws WeiboClientException { return sendRequestAndGetResponseObject(request, Paging.EMPTY, params, clazz); } public <T> T sendRequestAndGetResponseObject(OAuthRequest request, Paging paging, Class<T> clazz) throws WeiboClientException { return sendRequestAndGetResponseObject(request, paging, Parameters.create(), clazz); } public <T> T sendRequestAndGetResponseObject(OAuthRequest request, Paging paging, Parameters params, Class<T> clazz) throws WeiboClientException { if (paging != null) { params.add(paging); } params.appendTo(request); return sendRequestAndGetResponseObject(request, clazz); } public <T> T sendRequestAndGetResponseObject(OAuthRequest request, Class<T> clazz) throws WeiboClientException { Response response = request.send(); return parseJsonObject(response, clazz); } public OAuthRequest createGetRequest(String path) { return createRequest(Verb.GET, path); } public OAuthRequest createPostRequest(String path) { return createRequest(Verb.POST, path); } private OAuthRequest createRequest(Verb verb, String path) { OAuthRequest request = new OAuthRequest(verb, getFullPath(path)); setRequestTimeout(request); setRequestAccessToken(request); return request; } private void setRequestTimeout(OAuthRequest request) { request.setConnectTimeout(connectTimeoutDuration, connectTimeoutUnit); request.setReadTimeout(readTimeoutDuration, readTimeoutUnit); } private void setRequestAccessToken(OAuthRequest request) { if (accessToken != null) { request.addHeader("Authorization", "OAuth2 " + accessToken.getToken()); } } public String getFullPath(String path) { if (path.startsWith("http://") || path.startsWith("https://")) { return path; } else { return API2_URL + path + ".json"; } } protected Map<String, String> mergeSingleItemMap(List<Map<String, String>> response) { Map<String, String> map = new HashMap<String, String>(); for (Map<String, String> item : response) { map.putAll(item); } return map; } protected ParameterAction urlParam(final URL url) { return new ParameterAction() { public void addParameter(Parameters params) { if (url != null) { params.add("url", url.toExternalForm()); } } }; } @JsonIgnoreProperties(ignoreUnknown = true) protected static class TagActionResponse { private long tagid; public static List<Long> toLongList(List<TagActionResponse> responseList) { List<Long> result = new ArrayList<Long>(responseList.size()); for (TagActionResponse response : responseList) { result.add(response.getTagid()); } return result; } public long getTagid() { return tagid; } public void setTagid(long tagid) { this.tagid = tagid; } } @JsonIgnoreProperties(ignoreUnknown = true) protected static class LongIdStringValue { private long id; private String value; public long getId() { return id; } public void setId(long id) { this.id = id; } public String getValue() { return value; } public void setValue(String value) { this.value = value; } } @JsonIgnoreProperties(ignoreUnknown = true) protected static class FollowTrendResponse { private long topicid; public long getTopicid() { return topicid; } public void setTopicid(long topicid) { this.topicid = topicid; } } @JsonIgnoreProperties(ignoreUnknown = true) protected static class UrlInfoResponse { private List<UrlInfo> urls; public List<UrlInfo> getUrls() { return urls; } public void setUrls(List<UrlInfo> urls) { this.urls = urls; } } @JsonIgnoreProperties(ignoreUnknown = true) protected static class UrlResponse { private List<Url> urls; public List<Url> getUrls() { return urls; } public void setUrls(List<Url> urls) { this.urls = urls; } } @JsonIgnoreProperties(ignoreUnknown = true) protected static class ResultResponse { private boolean result; public boolean isResult() { return result; } public void setResult(boolean result) { this.result = result; } } @JsonIgnoreProperties(ignoreUnknown = true) protected static class StatusResponse { private int status; public int getStatus() { return status; } public void setStatus(int status) { this.status = status; } } }