/*
 * Copyright 2008-2010 Microarray Informatics Team, EMBL-European Bioinformatics Institute
 *
 * 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.
 *
 *
 * For further details of the Gene Expression Atlas project, including source code,
 * downloads and documentation, please see:
 *
 * http://gxa.github.com/gxa
 */

package uk.ac.ebi.gxa.requesthandlers.base;

import uk.ac.ebi.gxa.requesthandlers.base.restutil.JsonRestResultRenderer;
import uk.ac.ebi.gxa.requesthandlers.base.restutil.RestResultRenderer;
import uk.ac.ebi.gxa.requesthandlers.base.restutil.XmlRestResultRenderer;
import uk.ac.ebi.gxa.requesthandlers.base.restutil.RestResultRenderException;
import uk.ac.ebi.gxa.requesthandlers.base.result.ErrorResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.HttpRequestHandler;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.EnumMap;

/**
 * REST API base servlet, implementing common functions as output format and style parameters handling,
 * GET/POST unification, exception handling etc.
 * @author pashky
 */
public abstract class AbstractRestRequestHandler implements HttpRequestHandler {
    protected Logger log = LoggerFactory.getLogger(getClass());
    private static final RestResultRenderer.ErrorWrapper ERROR_WRAPPER = new RestResultRenderer.ErrorWrapper() {
        public Object wrapError(Throwable e) {
            return new ErrorResult(e);
        }
    };
    private static final String XML_ROOTNAME = "atlasResponse";

    private static enum Format {
        JSON, XML;
        static Format parse(String s) {
            try {
                return Format.valueOf(s.toUpperCase());
            } catch(Exception e) {
                return JSON;
            }
        }
    }

    private Class profile = Object.class;

    /**
     * Use this function to set REST output formatter profile, to deal properly with the result of doRest() method
     * @param profile profile class
     */
    protected void setRestProfile(Class profile) {
        this.profile = profile;
    }

    public void handleRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        boolean indent = request.getParameter("indent") != null;
        Format format = Format.parse(request.getParameter("format"));
        try {
            Object o;
            try {
                o = process(request);
            } catch (final RuntimeException e) {
                log.error("Exception in servlet process()", e);
                o = new ErrorResult(e);
            }

            RestResultRenderer renderer;
            switch (format) {
                case XML: {
                    response.setContentType("text/xml");
                    response.setCharacterEncoding("utf-8");
                    renderer = new XmlRestResultRenderer(indent, 4, XML_ROOTNAME);
                }
                break;
                case JSON: {
                    if(indent)
                        response.setContentType("application/javascript");
                    else
                        response.setContentType("application/json");
                    response.setCharacterEncoding("utf-8");
                    String jsonCallback = request.getParameter("callback");
                    if(jsonCallback != null)
                        jsonCallback = jsonCallback.replaceAll("[^a-zA-Z0-9_]", "");                    
                    renderer = new JsonRestResultRenderer(indent, 4, jsonCallback);
                }
                break;
                default:
                    renderer = null;
            }

            renderer.setErrorWrapper(ERROR_WRAPPER);
            renderer.render(o, response.getWriter(), profile);
        } catch (IOException e) {
            // i/o exception is bad, we probably better give up writing anything
            log.error("I/O exception", e);
        } catch (RestResultRenderException e) {
            fatal(format, "Response render exception", e, response.getWriter());
        }
    }

    private void fatal(Format f, String text, Throwable e, PrintWriter out) {
        log.error(text, e);
        switch (f) {
            case JSON:
                out.println("{error:\"Fatal error\"}");
                break;
            case XML:
                out.println("<?xml version=\"1.0\"?><" + XML_ROOTNAME + "><error>Fatal error</error></" + XML_ROOTNAME + ">");
                break;
        }
    }

    /**
     * Implement this method to process REST API requests
     * @param request HTTP request to handle
     * @return result object to be formatted with REST output formatter according to chosen by setRestProfile() mthod
     * profile.
     */
    public abstract Object process(HttpServletRequest request);
}


@@ -857,16 +857,179 @@
 .base;%0A%0A
+import org.slf4j.Logger;%0Aimport org.slf4j.LoggerFactory;%0Aimport org.springframework.web.HttpRequestHandler;%0Aimport sun.plugin.dom.exception.InvalidStateException;%0A
 import u
@@ -1154,34 +1154,41 @@
 RestResultRender
-er
+Exception
 ;%0Aimport uk.ac.e
@@ -1224,19 +1224,16 @@
 estutil.
-Xml
 RestResu
@@ -1287,32 +1287,35 @@
 s.base.restutil.
+Xml
 RestResultRender
@@ -1310,33 +1310,26 @@
 ResultRender
-Exception
+er
 ;%0Aimport uk.
@@ -1383,116 +1383,8 @@
 ult;
-%0Aimport org.slf4j.Logger;%0Aimport org.slf4j.LoggerFactory;%0Aimport org.springframework.web.HttpRequestHandler;
 %0A%0Aim
@@ -1572,34 +1572,8 @@
 ter;
-%0Aimport java.util.EnumMap;
 %0A%0A/*
@@ -1727,16 +1727,19 @@
 ng etc.%0A
+ *%0A
  * @auth
@@ -2230,16 +2230,17 @@
 N, XML;%0A
+%0A
         
@@ -2364,16 +2364,17 @@
  %7D catch
+ 
 (Excepti
@@ -2603,24 +2603,31 @@
 st() method%0A
+     *%0A
      * @para
@@ -3661,16 +3661,17 @@
       if
+ 
 (indent)
@@ -3998,16 +3998,17 @@
       if
+ 
 (jsonCal
@@ -4106,36 +4106,16 @@
 %5D%22, %22%22);
-                    
 %0A       
@@ -4281,23 +4281,68 @@
     
-renderer = null
+throw new InvalidStateException(%22Unknown format: %22 + format)
 ;%0A  
@@ -5258,16 +5258,23 @@
 equests%0A
+     *%0A
      * @
@@ -5434,16 +5434,24 @@
 d%0A     *
+        
  profile

Possible null pointer dereference There is a branch of statement that, if executed, guarantees that a null value will be dereferenced, which would generate a NullPointerException when the code is executed. Of course, the problem might be that the branch or statement is infeasible and that the null pointer exception can't ever be executed; deciding that is beyond the ability of FindBugs.