package in.partake.controller.api; import in.partake.controller.base.AbstractPartakeController; import in.partake.resource.ServerErrorCode; import in.partake.resource.UserErrorCode; import java.nio.charset.Charset; import java.util.Map; import java.util.Map.Entry; import org.codehaus.jackson.node.JsonNodeFactory; import org.codehaus.jackson.node.ObjectNode; import play.Logger; import play.mvc.Result; public abstract class AbstractPartakeAPI extends AbstractPartakeController { // TODO(mayah): UTF8 should be shared around the project, I believe. private static final Charset UTF8 = Charset.forName("utf-8"); // ---------------------------------------------------------------------- // protected void addHeader(String key, String value) { response().getHeaders().put(key, value); } // ---------------------------------------------------------------------- // Rendering /** * JSON object をレスポンスとして返す。 * @param obj * @return */ protected Result renderJSON(ObjectNode obj) { return renderJSON(obj, OK); } protected Result renderJSON(ObjectNode obj, int status) { return renderJSONWith(obj, status, "application/json; charset=utf-8"); } protected Result renderJSONWith(ObjectNode obj, int status, String contentType) { assert obj != null; response().setContentType(contentType); response().setHeader("Cache-Control", "no-cache"); return status(status, obj.toString().getBytes(UTF8)); } /** * <code>{ "result": "ok" }</code> をレスポンスとして返す。 * with status code 200. * @return */ protected Result renderOK() { return renderOK(new ObjectNode(JsonNodeFactory.instance)); } /** * obj に result: ok を追加して返す。obj に result が既に含まれていれば RuntimeException を投げる。 * @param obj * @return */ protected Result renderOK(ObjectNode obj) { if (obj.has("result")) throw new RuntimeException("obj should not contain result"); obj.put("result", "ok"); return renderJSON(obj); } @Deprecated protected Result renderOKWith(ObjectNode obj, String contentType) { if (obj.has("result")) throw new RuntimeException("obj should not contain result"); obj.put("result", "ok"); return renderJSONWith(obj, OK, contentType); } /** * <code>{ "result": "error", "reason": reason }</code> をレスポンスとして返す。 * ステータスコードは 500 を返す。 */ @Override protected Result renderError(ServerErrorCode errorCode, Map<String, String> additionalInfo, Throwable e) { assert errorCode != null; final String reasonString = errorCode.toString() + ":" + errorCode.getReasonString(); if (e != null) { Logger.error(reasonString, e); } else { Logger.error(reasonString); } ObjectNode obj = new ObjectNode(JsonNodeFactory.instance); obj.put("result", "error"); obj.put("reason", errorCode.getReasonString()); if (additionalInfo != null) { ObjectNode info = new ObjectNode(JsonNodeFactory.instance); for (Entry<String, String> entry : additionalInfo.entrySet()) info.put(entry.getKey(), entry.getValue()); obj.put("additional", info); } return renderJSON(obj, INTERNAL_SERVER_ERROR); } @Override protected Result renderInvalid(UserErrorCode ec, Map<String, String> additionalInfo, Throwable e) { assert ec != null; if (e != null) Logger.info("renderInvalid", e); ObjectNode obj = new ObjectNode(JsonNodeFactory.instance); obj.put("result", "invalid"); obj.put("reason", ec.getReasonString()); if (additionalInfo != null) { ObjectNode info = new ObjectNode(JsonNodeFactory.instance); for (Entry<String, String> entry : additionalInfo.entrySet()) info.put(entry.getKey(), entry.getValue()); obj.put("additional", info); } return renderJSON(obj, BAD_REQUEST); } protected Result renderLoginRequired() { ObjectNode obj = new ObjectNode(JsonNodeFactory.instance); obj.put("result", "auth"); obj.put("reason", "login is required"); addHeader("WWW-Authenticate", "OAuth"); return renderJSON(obj, UNAUTHORIZED); } protected Result renderForbidden() { ObjectNode obj = new ObjectNode(JsonNodeFactory.instance); obj.put("result", "forbidden"); obj.put("reason", "forbidden action"); return renderJSON(obj, FORBIDDEN); } protected Result renderForbidden(UserErrorCode ec) { ObjectNode obj = new ObjectNode(JsonNodeFactory.instance); obj.put("result", "forbidden"); obj.put("reason", ec.getReasonString()); obj.put("errorCode", ec.toString()); return renderJSON(obj, FORBIDDEN); } protected Result renderNotFound() { ObjectNode obj = new ObjectNode(JsonNodeFactory.instance); obj.put("result", "notfound"); obj.put("reason", "not found"); return renderJSON(obj, NOT_FOUND); } }