001/**
002 * Copyright 2014 Tampere University of Technology, Pori Department
003 * 
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 * 
008 *   http://www.apache.org/licenses/LICENSE-2.0
009 * 
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package core.tut.pori.http;
017
018import java.io.IOException;
019
020import javax.servlet.http.HttpServletResponse;
021
022import org.apache.log4j.Logger;
023
024import core.tut.pori.utils.JSONFormatter;
025
026/**
027 * 
028 * Response object that supports JSON output.
029 * 
030 * Note that you MUST use this class if you plan to use JSON output, the ResponseData is one you should use if you need XML output.
031 *
032 */
033public class JSONResponse extends Response {
034  private static final Logger LOGGER = Logger.getLogger(JSONResponse.class);
035  private JSONResponseData _responseData = null;
036
037  /**
038   * This method replaces the default XML/JAXB output with JSON using GSON annotations
039   * and sets content type to {@value core.tut.pori.http.Definitions#CONTENT_TYPE_JSON}.
040   * These to parameters should be changed for the response if format is changed in the overriding method.
041   * 
042   * Additionally this method sets the HTTP basic authentication header if the status is set {@link core.tut.pori.http.Response.Status#UNAUTHORIZED}.
043   * 
044   * @param response
045   */
046  @Override
047  public void writeTo(HttpServletResponse response) {
048    JSONResponseData data = _responseData;
049    if(data == null){ // create new response if one does not already exist
050      data = new DefaultJSONResponse(getMessage(), getMethod(), getService(), getStatus());
051    }else{ // make sure the details in the response are up to date
052      data._message = getMessage();
053      data._method = getMethod();
054      data._service = getService();
055      data._stat = getStatus();
056    }
057    
058    try {
059      response.setContentType(Definitions.CONTENT_TYPE_JSON);
060      response.setCharacterEncoding(Definitions.ENCODING_UTF8);
061      response.getWriter().write(JSONFormatter.createGsonSerializer().toJson(data));
062    } catch (IOException ex) {
063      LOGGER.error(ex, ex);
064      setStatus(Status.INTERNAL_SERVER_ERROR);
065    }
066    
067    Status stat = getStatus();
068    if(stat != Status.OK){  // don't change defaults if there is OK status
069      response.setStatus(stat.toStatusCode());
070      if(stat == Status.UNAUTHORIZED){
071        setDefaultAuthenticationHeader(response);
072      }
073    }
074  }
075  
076  /**
077   * @throws UnsupportedOperationException if data is not of type {@link core.tut.pori.http.JSONResponseData}
078   * @see #setResponseData(JSONResponseData)
079   */
080  @Override
081  public void setResponseData(ResponseData data) throws UnsupportedOperationException {
082    if(data == null){
083      setResponseData((JSONResponseData)null);
084    }else if(data instanceof JSONResponseData){
085      setResponseData((JSONResponseData)data);
086    }else{
087      throw new UnsupportedOperationException("Unsupported data type: "+data.getClass().toString());
088    }
089  }
090  
091  /**
092   * 
093   */
094  public JSONResponse() {
095    super();
096  }
097
098  /**
099   * 
100   * @param data
101   * @throws UnsupportedOperationException if the given data is not of type JSONResponseData
102   */
103  public JSONResponse(ResponseData data) throws UnsupportedOperationException {
104    super();
105    setResponseData(data);
106  }
107  
108  /**
109   * 
110   * @param data
111   */
112  public JSONResponse(JSONResponseData data){
113    _responseData = data;
114  }
115
116  /**
117   * 
118   * @param stat
119   * @param message
120   */
121  public JSONResponse(Status stat, String message) {
122    super(stat, message);
123  }
124
125  /**
126   * 
127   * @param stat
128   */
129  public JSONResponse(Status stat) {
130    super(stat);
131  }
132
133  /**
134   * 
135   * @param data
136   */
137  public void setResponseData(JSONResponseData data){
138    _responseData = data;
139  }
140
141  /**
142   * default implementation
143   *
144   */
145  private class DefaultJSONResponse extends JSONResponseData{
146    /**
147     * 
148     * @param message
149     * @param method
150     * @param service
151     * @param status
152     */
153    public DefaultJSONResponse(String message, String method, String service, Status status){
154      _message = message;
155      _method = method;
156      _service = service;
157      _stat = status;
158    }
159  } // class DefaultGSONResponse 
160}