001/*
002 * (C) Copyright 2011 Nuxeo SA (http://nuxeo.com/) and others.
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 *
016 * Contributors:
017 *     Julien Carsique
018 *
019 */
020
021package org.nuxeo.ecm.core.management.statuses;
022
023import java.io.IOException;
024import java.io.OutputStream;
025
026import javax.servlet.ServletException;
027import javax.servlet.http.HttpServlet;
028import javax.servlet.http.HttpServletRequest;
029import javax.servlet.http.HttpServletResponse;
030
031import org.apache.commons.lang3.StringUtils;
032import org.apache.commons.logging.Log;
033import org.apache.commons.logging.LogFactory;
034import org.nuxeo.common.Environment;
035import org.nuxeo.ecm.core.management.api.ProbeManager;
036import org.nuxeo.runtime.RuntimeService;
037import org.nuxeo.runtime.api.Framework;
038
039/**
040 * Servlet for retrieving Nuxeo services running status.
041 *
042 * @since 9.3 this servlet returns a status based of all the probes registered for the healthCheck.
043 */
044public class StatusServlet extends HttpServlet {
045
046    private static final long serialVersionUID = 1L;
047
048    private static final Log log = LogFactory.getLog(StatusServlet.class);
049
050    public static final String PARAM = "info";
051
052    public static final String PARAM_STARTED = "started";
053
054    public static final String PARAM_SUMMARY = "summary";
055
056    public static final String PARAM_SUMMARY_KEY = "key";
057
058    public static final String PARAM_RELOAD = "reload";
059
060    public static final String PROBE_PARAM = "probe";
061
062    @Override
063    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
064        String param = req.getParameter(PARAM);
065        if (param != null) {
066            doPost(req, resp);
067        } else {
068            HealthCheckResult result = getOrRunHealthCheck(null);
069            sendHealthCheckResponse(resp, result);
070        }
071    }
072
073    protected void sendHealthCheckResponse(HttpServletResponse resp, HealthCheckResult result) throws IOException {
074        if (result.isHealthy()) {
075            resp.setStatus(HttpServletResponse.SC_OK);
076        } else {
077            resp.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
078        }
079        sendResponse(resp, result.toJson());
080    }
081
082    @Override
083    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
084        StringBuilder response = new StringBuilder();
085        String requestedInfo = req.getParameter(PARAM);
086        if (requestedInfo.equals(PARAM_STARTED)) {
087            getStartedInfo(response);
088        } else if (requestedInfo.equals(PARAM_SUMMARY)) {
089            String givenKey = req.getParameter(PARAM_SUMMARY_KEY);
090            if (Framework.getRuntime().getProperty(Environment.SERVER_STATUS_KEY).equals(givenKey)) {
091                getSummaryInfo(response);
092            } else {
093                resp.setStatus(HttpServletResponse.SC_FORBIDDEN);
094            }
095        } else if (requestedInfo.equals(PARAM_RELOAD)) {
096            if (isStarted()) {
097                response.append("reload();");
098            } else {
099                resp.setStatus(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
100            }
101        } else if (requestedInfo.equals(PROBE_PARAM)) {
102            String probetoEval = req.getParameter(PARAM_SUMMARY_KEY);
103            try {
104                HealthCheckResult result = getOrRunHealthCheck(probetoEval);
105                sendHealthCheckResponse(resp, result);
106            } catch (IllegalArgumentException e) {
107                resp.setStatus(HttpServletResponse.SC_NOT_FOUND);
108            }
109        }
110        sendResponse(resp, response.toString());
111    }
112
113    protected void sendResponse(HttpServletResponse resp, String response) throws IOException {
114        resp.setContentType("application/json");
115        resp.setContentLength(response.getBytes().length);
116        OutputStream out = resp.getOutputStream();
117        out.write(response.getBytes());
118        out.close();
119    }
120
121    protected void getSummaryInfo(StringBuilder response) {
122        if (isStarted()) {
123            StringBuilder msg = new StringBuilder();
124            boolean isFine = Framework.getRuntime().getStatusMessage(msg);
125            response.append(isFine).append("\n");
126            response.append(msg);
127        } else {
128            response.append(false).append("\n");
129            response.append("Runtime failed to start");
130        }
131    }
132
133    protected void getStartedInfo(StringBuilder response) {
134        response.append(isStarted()).toString();
135    }
136
137    private boolean isStarted() {
138        RuntimeService runtimeService = Framework.getRuntime();
139        return runtimeService != null && runtimeService.isStarted();
140    }
141
142    @Override
143    public void init() throws ServletException {
144        log.debug("Ready.");
145    }
146
147    protected HealthCheckResult getOrRunHealthCheck(String probe) {
148        ProbeManager pm = Framework.getService(ProbeManager.class);
149        if (StringUtils.isEmpty(probe)) { // run all healthCheck probes
150            return pm.getOrRunHealthChecks();
151        } else {
152            return pm.getOrRunHealthCheck(probe);
153        }
154    }
155}