/**
* personium.io
* Copyright 2014 FUJITSU LIMITED
*
* 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 com.fujitsu.dc.client.http;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Map;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpEntityEnclosingRequest;
import org.apache.http.HttpHeaders;
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.client.methods.HttpPut;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.entity.InputStreamEntity;
import org.apache.http.entity.StringEntity;
import com.fujitsu.dc.client.DaoException;
import com.fujitsu.dc.client.utils.Log;
///**
// * リクエストオブジェクトを生成するBuilderクラス.
// */
/**
* It creates a new object of DcHttpClient. This is a builder class that generates a request header object.
*/
public class DcRequestBuilder {
// /** ログオブジェクト. */
/** Log object. */
private Log log = new Log(DcRequestBuilder.class);
// /** URL文字列. */
/** URL string. */
private String urlValue = null;
/** Http Request Headers. */
private Map<String, String> headers = new HashMap<String, String>();
// /** Method値. */
/** Method Value. */
private String methodValue = null;
// /** Token値. */
/** Token Value. */
private String tokenValue = null;
// /** Body値. */
/** Body Value. */
private String bodyValue = null;
// /** Body(InputStream)値. */
/** Body(InputStream) Value. */
private InputStream bodyStream = null;
// /** デフォルトヘッダ. */
/** Default Headers. */
private HashMap<String, String> defaultHeaders;
// /** 日本語UTFのためのマスク値. */
/** Mask value for Japanese UTF. */
public static final int CHAR_MASK = 0x7f;
// /** 日本語UTFのためのマスク値. */
/** Mask value for Japanese UTF. */
public static final int CHAR_JPUTF_MASK = 0x10000;
// /**
// * コンストラクタ.
// */
/**
* This is the default constructor.
*/
public DcRequestBuilder() {
}
/**
* This method is used to get Http Request Headers.
* @return map of headers
*/
public Map<String, String> getHeaders() {
return headers;
}
// /**
// * URL文字列の取得.
// * @return URL文字列
// */
/**
* This method is used to get the URL value.
* @return URL string.
*/
public String getUrl() {
return this.urlValue;
}
/**
* This method is used to get the ContentType.
* @return ContentType Value
*/
public String getContentType() {
return this.headers.get(HttpHeaders.CONTENT_TYPE);
}
/**
* This method is used to get the ContentLength.
* @return ContentLength value
*/
public String getContentLength() {
return this.headers.get(HttpHeaders.CONTENT_LENGTH);
}
// /**
// * Acceptの取得.
// * @return Accept Value
// */
/**
* This method is used to get the accept parameter in header.
* @return accept value
*/
public String getAccept() {
return this.headers.get(HttpHeaders.ACCEPT);
}
// /**
// * Methodの取得.
// * @return Method
// */
/**
* This method is used to get the method value.
* @return Method value
*/
public String getMethod() {
return this.methodValue;
}
// /**
// * Tokenの取得.
// * @return Token値
// */
/**
* This method is used to get the token value.
* @return Token value
*/
public String getToken() {
return this.tokenValue;
}
// /**
// * AcceptEncodingを取得.
// * @return AcceptEncoding Header Value
// */
/**
* This method is used to get the accept encoding parameter in header.
* @return Accept Encoding value
*/
public String getAcceptEncoding() {
return this.headers.get(HttpHeaders.ACCEPT_ENCODING);
}
// /**
// * Depth値を取得.
// * @return Depth Header Value
// */
/**
* This method is used to get the depth parameter in header.
* @return Depth value
*/
public String getDepth() {
return this.headers.get(HttpHeaders.DEPTH);
}
// /**
// * IF-MATCH値を取得.
// * @return IF-MATCH Header Value
// */
/**
* This method is used to get the if match parameter in header.
* @return IfMatch value
*/
public String getIfMatch() {
return this.headers.get(HttpHeaders.IF_MATCH);
}
// /**
// * IF-NONE-MATCH値を取得.
// * @return IF-NONE-MATCH Header Value
// */
/**
* This method is used to get the if none match parameter in header.
* @return IfNoneMatch value
*/
public String getIfNoneMatch() {
return this.headers.get(HttpHeaders.IF_NONE_MATCH);
}
// /**
// * Body(String)の取得.
// * @return Body値
// */
/**
* This method is used to get the Body(String).
* @return Body value
*/
public String getBody() {
return this.bodyValue;
}
// /**
// * Body(InputStream)の取得.
// * @return Body値
// */
/**
* This method is used to get the Body(InputStream).
* @return BodyStream value
*/
public InputStream getBodyStream() {
return this.bodyStream;
}
// /**
// * URLをセットする.
// * @param value URL文字列
// * @return 自分自身のオブジェクト
// */
/**
* This method is used to set the URL string.
* @param value URL string
* @return DcRequestBuilder Its own object
*/
public DcRequestBuilder url(String value) {
this.urlValue = value;
return this;
}
// /**
// * Acceptをセットする.
// * @param value Accept Header Value
// * @return 自分自身のオブジェクト
// */
/**
* This method is used to set the accept Header value.
* @param value Accept Header Value
* @return DcRequestBuilder Its own object
*/
public DcRequestBuilder accept(String value) {
if (value != null) {
this.headers.put(HttpHeaders.ACCEPT, value);
}
return this;
}
// /**
// * ContentTypeをセットする.
// * @param value ContentType Header Value
// * @return 自分自身のオブジェクト
// */
/**
* This method is used to set the ContentType Header value.
* @param value ContentType Header Value
* @return DcRequestBuilder Its own object
*/
public DcRequestBuilder contentType(String value) {
if (value != null) {
this.headers.put(HttpHeaders.CONTENT_TYPE, value);
}
return this;
}
// /**
// * ContentLength.
// * @param value content length Header Value
// * @return 自分自身のオブジェクト
// */
/**
* This method is used to set the ContentLength Header value.
* @param value content length Header Value
* @return DcRequestBuilder Its own object
*/
public DcRequestBuilder contentLength(String value) {
if (value != null) {
this.headers.put(HttpHeaders.CONTENT_LENGTH, value);
}
return this;
}
// /**
// * Methodをセットする.
// * @param value Method値
// * @return 自分自身のオブジェクト
// */
/**
* This method is used to set the method value.
* @param value Method
* @return DcRequestBuilder Its own object
*/
public DcRequestBuilder method(String value) {
this.methodValue = value;
return this;
}
// /**
// * Tokenをセットする.
// * @param value Token値
// * @return 自分自身のオブジェクト
// */
/**
* This method is used to set the token value.
* @param value TokenValue
* @return DcRequestBuilder Its own object
*/
public DcRequestBuilder token(String value) {
if (value != null) {
this.tokenValue = value;
}
return this;
}
// /**
// * AcceptEncodingをセットする.
// * @param value AcceptEncoding Header Value
// * @return 自分自身のオブジェクト
// */
/**
* This method is used to set the acceptEncoding Header value.
* @param value AcceptEncoding Header Value
* @return DcRequestBuilder Its own object
*/
public DcRequestBuilder acceptEncoding(String value) {
if (value != null) {
this.headers.put(HttpHeaders.ACCEPT_ENCODING, value);
}
return this;
}
// /**
// * IF-MATCHをセットする.
// * @param value IF-MATCH Header Value
// * @return 自分自身のオブジェクト
// */
/**
* This method is used to set the IF-MATCH Header value.
* @param value IF-MATCH Header Value
* @return DcRequestBuilder Its own object
*/
public DcRequestBuilder ifMatch(String value) {
if (value != null) {
this.headers.put(HttpHeaders.IF_MATCH, value);
}
return this;
}
// /**
// * IF-NONE-MATCHをセットする.
// * @param value IF-NONE-MATCH Header Value
// * @return 自分自身のオブジェクト
// */
/**
* This method is used to set the IF-NONE-MATCH Header value.
* @param value IF-NONE-MATCH Header Value
* @return DcRequestBuilder Its own object
*/
public DcRequestBuilder ifNoneMatch(String value) {
if (value != null) {
this.headers.put(HttpHeaders.IF_NONE_MATCH, value);
}
return this;
}
// /**
// * Depthをセットする.
// * @param value Depth Header Value
// * @return 自分自身のオブジェクト
// */
/**
* This method is used to set the Depth Header value.
* @param value Depth Header Value
* @return DcRequestBuilder Its own object
*/
public DcRequestBuilder depth(String value) {
if (value != null) {
this.headers.put(HttpHeaders.DEPTH, value);
}
return this;
}
// /**
// * Body(文字列)をセットする.
// * @param value Body値
// * @return 自分自身のオブジェクト
// */
/**
* This method is used to set the Body string value.
* @param value Body String
* @return DcRequestBuilder Its own object
*/
public DcRequestBuilder body(String value) {
this.bodyValue = value;
return this;
}
// /**
// * Body(Stream)をセットする.
// * @param is Body値
// * @return 自分自身のオブジェクト
// */
/**
* This method is used to set the Body stream value.
* @param is Body Stream
* @return DcRequestBuilder Its own object
*/
public DcRequestBuilder body(InputStream is) {
this.bodyStream = is;
return this;
}
// /**
// * デフォルトヘッダをセットする.
// * @param value デフォルトヘッダ
// * @return 自分自身のオブジェクト
// */
/**
* This method is used to set the Default Headers value.
* @param value Default Headers
* @return DcRequestBuilder Its own object
*/
public DcRequestBuilder defaultHeaders(HashMap<String, String> value) {
this.defaultHeaders = value;
return this;
}
/**
* This method sets an arbitrary HTTP request header.
* @param name arbitrary header name
* @param value value for the header
* @return DcRequestBuilder Its own object
*/
public DcRequestBuilder header(String name, String value) {
this.headers.put(name, value);
return this;
}
// /**
// * HttpUriRequestオブジェクトを生成する.
// * @return 生成したHttpUriRequestオブジェクト
// * @throws DaoException DAO例外
// */
/**
* This method is used to generate a HttpUriRequest object by setting the parameters in request header.
* @return HttpUriRequest object that is generated
* @throws DaoException Exception thrown
*/
public HttpUriRequest build() throws DaoException {
HttpUriRequest req = null;
if (HttpMethods.PUT.equals(this.methodValue)) {
req = new HttpPut(this.urlValue);
} else if (HttpMethods.POST.equals(this.methodValue)) {
req = new HttpPost(this.urlValue);
} else if (HttpMethods.DELETE.equals(this.methodValue)) {
req = new HttpDelete(this.urlValue);
} else if (HttpMethods.ACL.equals(this.methodValue)) {
req = new HttpAclMethod(this.urlValue);
} else if (HttpMethods.MKCOL.equals(this.methodValue)) {
req = new HttpMkColMethod(this.urlValue);
} else if (HttpMethods.PROPPATCH.equals(this.methodValue)) {
req = new HttpPropPatchMethod(this.urlValue);
} else if (HttpMethods.PROPFIND.equals(this.methodValue)) {
req = new HttpPropfindMethod(this.urlValue);
} else if (HttpMethods.GET.equals(this.methodValue)) {
req = new HttpGet(this.urlValue);
} else if (HttpMethods.MERGE.equals(this.methodValue)) {
req = new HttpMergeMethod(this.urlValue);
}
if (this.tokenValue != null) {
req.addHeader(HttpHeaders.AUTHORIZATION, "Bearer " + this.tokenValue);
}
/** include header parameters if any. */
for (String key : headers.keySet()) {
String value = headers.get(key);
req.addHeader(key, value);
}
// デフォルトヘッダがセットされていれば、それらを設定。
/** If Default header is set, configure them. */
// 最初にセットしない理由は、リクエストヘッダは、同名ヘッダが複数登録されてしまうため
/**
* The reason you do not want to set for the first time, since the request header, would have been more than one
* registration is the same name header
*/
if (this.defaultHeaders != null) {
for (String key : this.defaultHeaders.keySet()) {
String val = this.defaultHeaders.get(key);
Header[] headerItems = req.getHeaders(key);
if (headerItems.length == 0) {
req.addHeader(key, val);
}
}
}
if (this.bodyValue != null) {
HttpEntity body = null;
try {
if (this.getContentType() != "" && RestAdapter.CONTENT_TYPE_JSON.equals(this.getContentType())) {
String bodyStr = toUniversalCharacterNames(this.bodyValue);
body = new StringEntity(bodyStr);
} else {
body = new StringEntity(this.bodyValue, RestAdapter.ENCODE);
}
} catch (UnsupportedEncodingException e) {
throw DaoException.create("error while request body encoding : " + e.getMessage(), 0);
}
((HttpEntityEnclosingRequest) req).setEntity(body);
}
if (this.bodyStream != null) {
InputStreamEntity body = new InputStreamEntity(this.bodyStream, -1);
body.setChunked(true);
this.bodyValue = "[stream]";
((HttpEntityEnclosingRequest) req).setEntity(body);
}
if (req != null) {
log.debug("");
log.debug("【Request】 " + req.getMethod() + " " + req.getURI());
Header[] allheaders = req.getAllHeaders();
for (int i = 0; i < allheaders.length; i++) {
log.debug("RequestHeader[" + allheaders[i].getName() + "] : " + allheaders[i].getValue());
}
log.debug("RequestBody : " + bodyValue);
}
return req;
}
// /**
// * 日本語文字列エンコード.
// * @param inStr エンコード対象の文字列
// * @return エンコード後の文字列
// */
/**
* This method i used for Japanese string encoding.
* @param inStr String to be encoded
* @return String after encoding
*/
private String toUniversalCharacterNames(String inStr) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < inStr.length(); i++) {
int c = inStr.charAt(i);
if (c > CHAR_MASK) {
sb.append("\\u");
sb.append(Integer.toHexString(CHAR_JPUTF_MASK + c).substring(1));
} else {
sb.append((char) c);
}
}
return sb.substring(0, sb.length());
}
}