/* * Copyright 2007 Yusuke Yamamoto * * 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 twitter4j.http; import java.io.File; import java.io.InputStream; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.util.List; import java.util.Locale; /** * A data class representing HTTP Post parameter * * @author Yusuke Yamamoto - yusuke at mac.com */ public final class HttpParameter implements Comparable<HttpParameter> { private String name = null; private String value = null; private String fileName = null; private File file = null; private InputStream fileBody = null; private String overrideFileType; private static final String JPEG = "image/jpeg"; private static final String GIF = "image/gif"; private static final String PNG = "image/png"; private static final String OCTET = "application/octet-stream"; public HttpParameter(final String name, final boolean value) { this.name = name; this.value = String.valueOf(value); } public HttpParameter(final String name, final double value) { this.name = name; this.value = String.valueOf(value); } public HttpParameter(final String name, final File file) { this(name, file, null); } public HttpParameter(final String name, final File file, final String overrideContentType) { this.name = name; this.file = file; overrideFileType = overrideContentType; } public HttpParameter(final String name, final int value) { this.name = name; this.value = String.valueOf(value); } public HttpParameter(final String name, final long value) { this.name = name; this.value = String.valueOf(value); } public HttpParameter(final String name, final String value) { this.name = name; this.value = value; } public HttpParameter(final String name, final String fileName, final InputStream fileBody) { this(name, fileName, fileBody, null); } public HttpParameter(final String name, final String fileName, final InputStream fileBody, final String overrideFileType) { this.name = name; this.fileName = fileName; this.fileBody = fileBody; this.overrideFileType = overrideFileType; } @Override public int compareTo(final HttpParameter o) { int compared; final HttpParameter that = o; compared = name.compareTo(that.name); if (0 == compared) { compared = value.compareTo(that.value); } return compared; } @Override public boolean equals(final Object o) { if (this == o) return true; if (!(o instanceof HttpParameter)) return false; final HttpParameter that = (HttpParameter) o; if (file != null ? !file.equals(that.file) : that.file != null) return false; if (fileBody != null ? !fileBody.equals(that.fileBody) : that.fileBody != null) return false; if (!name.equals(that.name)) return false; if (value != null ? !value.equals(that.value) : that.value != null) return false; return true; } /** * @return content-type */ public String getContentType() { if (!isFile()) throw new IllegalStateException("not a file"); if (overrideFileType != null) return overrideFileType; String contentType; String extensions = getFileName(); final int index = extensions.lastIndexOf("."); if (-1 == index) { // no extension contentType = OCTET; } else { extensions = extensions.substring(extensions.lastIndexOf(".") + 1).toLowerCase(Locale.US); if (extensions.length() == 3) { if ("gif".equals(extensions)) { contentType = GIF; } else if ("png".equals(extensions)) { contentType = PNG; } else if ("jpg".equals(extensions)) { contentType = JPEG; } else { contentType = OCTET; } } else if (extensions.length() == 4) { if ("jpeg".equals(extensions)) { contentType = JPEG; } else { contentType = OCTET; } } else { contentType = OCTET; } } return contentType; } public File getFile() { return file; } public InputStream getFileBody() { return fileBody; } public String getFileName() { return file != null ? file.getName() : fileName; } public String getName() { return name; } public String getValue() { return value; } public boolean hasFileBody() { return fileBody != null; } @Override public int hashCode() { int result = name.hashCode(); result = 31 * result + (value != null ? value.hashCode() : 0); result = 31 * result + (file != null ? file.hashCode() : 0); result = 31 * result + (fileBody != null ? fileBody.hashCode() : 0); return result; } public boolean isFile() { return fileBody != null || file != null; } @Override public String toString() { return "PostParameter{" + "name='" + name + '\'' + ", value='" + value + '\'' + ", file=" + file + ", fileBody=" + fileBody + '}'; } public static boolean containsFile(final HttpParameter[] params) { boolean containsFile = false; if (null == params) return false; for (final HttpParameter param : params) { if (param.isFile()) { containsFile = true; break; } } return containsFile; } /** * @param value string to be encoded * @return encoded string * @see <a href="http://wiki.oauth.net/TestCases">OAuth / TestCases</a> * @see <a * href="http://groups.google.com/group/oauth/browse_thread/thread/a8398d0521f4ae3d/9d79b698ab217df2?hl=en&lnk=gst&q=space+encoding#9d79b698ab217df2">Space * encoding - OAuth | Google Groups</a> * @see <a href="http://tools.ietf.org/html/rfc3986#section-2.1">RFC 3986 - * Uniform Resource Identifier (URI): Generic Syntax - 2.1. * Percent-Encoding</a> */ public static String encode(final String value) { String encoded; try { encoded = URLEncoder.encode(value, "UTF-8"); } catch (final UnsupportedEncodingException ignore) { return null; } final StringBuilder buf = new StringBuilder(encoded.length()); char focus; for (int i = 0; i < encoded.length(); i++) { focus = encoded.charAt(i); if (focus == '*') { buf.append("%2A"); } else if (focus == '+') { buf.append("%20"); } else if (focus == '%' && i + 1 < encoded.length() && encoded.charAt(i + 1) == '7' && encoded.charAt(i + 2) == 'E') { buf.append('~'); i += 2; } else { buf.append(focus); } } return buf.toString(); } public static String encodeParameters(final HttpParameter[] httpParams) { if (null == httpParams) return ""; final StringBuilder buf = new StringBuilder(); for (int j = 0; j < httpParams.length; j++) { if (httpParams[j].isFile()) throw new IllegalArgumentException("parameter [" + httpParams[j].name + "]should be text"); if (j != 0) { buf.append("&"); } buf.append(encode(httpParams[j].name)).append("=").append(encode(httpParams[j].value)); } return buf.toString(); } public static HttpParameter[] getParameterArray(final String name, final int value) { return getParameterArray(name, String.valueOf(value)); } public static HttpParameter[] getParameterArray(final String name1, final int value1, final String name2, final int value2) { return getParameterArray(name1, String.valueOf(value1), name2, String.valueOf(value2)); } public static HttpParameter[] getParameterArray(final String name, final String value) { return new HttpParameter[]{new HttpParameter(name, value)}; } public static HttpParameter[] getParameterArray(final String name1, final String value1, final String name2, final String value2) { return new HttpParameter[]{new HttpParameter(name1, value1), new HttpParameter(name2, value2)}; } public static HttpParameter[] merge(final HttpParameter[] params, final HttpParameter... extraParams) { if (params == null) return extraParams; if (extraParams == null) return params; final HttpParameter[] merged = new HttpParameter[params.length + extraParams.length]; System.arraycopy(params, 0, merged, 0, params.length); System.arraycopy(extraParams, 0, merged, params.length, extraParams.length); return merged; } /* package */ static boolean containsFile(final List<HttpParameter> params) { boolean containsFile = false; for (final HttpParameter param : params) { if (param.isFile()) { containsFile = true; break; } } return containsFile; } }