View Javadoc
1   /*
2    * Copyright 2010-2012 Capgemini
3    * Licensed under the Apache License, Version 2.0 (the "License");
4    * you may not use this file except in compliance with the License.
5    * You may obtain a copy of the License at
6    *
7    * http://www.apache.org/licenses/LICENSE-2.0
8    *
9    * Unless required by applicable law or agreed to in writing, software
10   * distributed under the License is distributed on an "AS IS" BASIS,
11   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12   * See the License for the specific language governing permissions and
13   * limitations under the License.
14   *
15   */
16  package net.sf.appstatus.web.pages;
17  
18  import static java.util.Collections.sort;
19  import static net.sf.appstatus.web.HtmlUtils.applyLayout;
20  import static net.sf.appstatus.web.HtmlUtils.generateBeginTable;
21  import static net.sf.appstatus.web.HtmlUtils.generateEndTable;
22  import static net.sf.appstatus.web.HtmlUtils.generateHeaders;
23  import static net.sf.appstatus.web.HtmlUtils.generateRow;
24  import static net.sf.appstatus.web.HtmlUtils.json;
25  import static org.apache.commons.lang3.StringUtils.join;
26  
27  import java.io.IOException;
28  import java.io.UnsupportedEncodingException;
29  import java.util.HashMap;
30  import java.util.List;
31  import java.util.Map;
32  import java.util.Map.Entry;
33  
34  import javax.servlet.ServletOutputStream;
35  import javax.servlet.http.HttpServletRequest;
36  import javax.servlet.http.HttpServletResponse;
37  
38  import org.apache.commons.lang3.text.StrBuilder;
39  import org.slf4j.Logger;
40  import org.slf4j.LoggerFactory;
41  
42  import net.sf.appstatus.core.AppStatus;
43  import net.sf.appstatus.core.check.ICheckResult;
44  import net.sf.appstatus.web.StatusWebHandler;
45  
46  public class StatusPage extends AbstractPage {
47  
48  	private static final String ENCODING = "UTF-8";
49  
50  	private static Logger LOGGER = LoggerFactory.getLogger(StatusPage.class);
51  
52  	private static final String PAGECONTENTLAYOUT = "statusContentLayout.html";
53  
54  	/**
55  	 * Returns status icon id.
56  	 *
57  	 * @param result
58  	 * @return
59  	 */
60  	private static String getStatus(final ICheckResult result) {
61  
62  		if (result.getCode() == ICheckResult.OK) {
63  			return Resources.STATUS_OK;
64  		}
65  
66  		if (result.isFatal()) {
67  			return Resources.STATUS_ERROR;
68  		}
69  
70  		return Resources.STATUS_WARN;
71  	}
72  
73  	@Override
74  	public void doGet(final StatusWebHandler webHandler, final HttpServletRequest req, final HttpServletResponse resp)
75  			throws UnsupportedEncodingException, IOException {
76  
77  		if (req.getParameter("json") != null) {
78  			doGetJSON(webHandler, req, resp);
79  		} else {
80  			doGetHTML(webHandler, req, resp);
81  		}
82  
83  	}
84  
85  	public void doGetHTML(final StatusWebHandler webHandler, final HttpServletRequest req,
86  			final HttpServletResponse resp) throws UnsupportedEncodingException, IOException {
87  
88  		setup(resp, "text/html");
89  		final ServletOutputStream os = resp.getOutputStream();
90  
91  		final AppStatus appStatus = webHandler.getAppStatus();
92  
93  		final Map<String, String> valuesMap = new HashMap<String, String>();
94  		final List<ICheckResult> results = appStatus.checkAll(req.getLocale());
95  		sort(results);
96  		boolean statusOk = true;
97  		int statusCode = 200;
98  		for (final ICheckResult r : results) {
99  			if (r.getCode() != ICheckResult.OK && r.isFatal()) {
100 				statusCode = 500;
101 				statusOk = false;
102 				break;
103 			}
104 		}
105 
106 		if (statusOk && appStatus.isMaintenance()) {
107 			statusCode = 503;
108 		}
109 
110 		valuesMap.put("maintenanceModeActive", appStatus.isMaintenance() ? "on" : "off");
111 		valuesMap.put("nextMode", appStatus.isMaintenance() ? "available" : "maintenance");
112 
113 		valuesMap.put("statusOk", String.valueOf(statusOk));
114 		valuesMap.put("statusCode", String.valueOf(statusCode));
115 
116 		resp.setStatus(statusCode);
117 
118 		// STATUS TABLE
119 		final StrBuilder sbStatusTable = new StrBuilder();
120 		if (generateBeginTable(sbStatusTable, results.size())) {
121 
122 			generateHeaders(sbStatusTable, "", "Group", "Name", "Description", "Code", "Resolution");
123 
124 			for (final ICheckResult r : results) {
125 				generateRow(sbStatusTable, getStatus(r), r.getGroup(), r.getProbeName(), r.getDescription(),
126 						String.valueOf(r.getCode()), r.getResolutionSteps());
127 			}
128 			generateEndTable(sbStatusTable, results.size());
129 		}
130 		valuesMap.put("statusTable", sbStatusTable.toString());
131 
132 		// PROPERTIES TABLE
133 		final StrBuilder sbPropertiesTable = new StrBuilder();
134 		final Map<String, Map<String, String>> properties = appStatus.getProperties();
135 		if (generateBeginTable(sbPropertiesTable, properties.size())) {
136 
137 			generateHeaders(sbPropertiesTable, "", "Group", "Name", "Value");
138 
139 			for (final Entry<String, Map<String, String>> cat : properties.entrySet()) {
140 				final String category = cat.getKey();
141 
142 				for (final Entry<String, String> r : cat.getValue().entrySet()) {
143 					generateRow(sbPropertiesTable, Resources.STATUS_PROP, category, r.getKey(), r.getValue());
144 				}
145 
146 			}
147 			generateEndTable(sbPropertiesTable, properties.size());
148 		}
149 		valuesMap.put("propertiesTable", sbPropertiesTable.toString());
150 		final String content = applyLayout(valuesMap, PAGECONTENTLAYOUT);
151 
152 		valuesMap.clear();
153 		valuesMap.put("content", content);
154 		os.write(getPage(webHandler, valuesMap).getBytes(ENCODING));
155 	}
156 
157 	public void doGetJSON(final StatusWebHandler webHandler, final HttpServletRequest req,
158 			final HttpServletResponse resp) throws UnsupportedEncodingException, IOException {
159 
160 		setup(resp, "application/json");
161 
162 		final AppStatus appStatus = webHandler.getAppStatus();
163 
164 		final ServletOutputStream os = resp.getOutputStream();
165 		int statusCode = 200;
166 		final List<ICheckResult> results = appStatus.checkAll(req.getLocale());
167 		for (final ICheckResult r : results) {
168 			if (r.isFatal()) {
169 				resp.setStatus(500);
170 				statusCode = 500;
171 				break;
172 			}
173 		}
174 
175 		if (appStatus.isMaintenance()) {
176 			resp.setStatus(503);
177 			statusCode = 503;
178 		}
179 
180 		os.write("{".getBytes(ENCODING));
181 
182 		os.write((json("code", statusCode) + ",").getBytes(ENCODING));
183 		os.write(("\"status\" : [").getBytes(ENCODING));
184 
185 		boolean first = true;
186 		for (final ICheckResult r : results) {
187 			if (!first) {
188 				os.write((",").getBytes(ENCODING));
189 			}
190 
191 			os.write(("{" + join(new String[] { json("name", r.getProbeName()), json("group", r.getGroup()),
192 					json("description", r.getDescription()), json("resolution", r.getResolutionSteps()),
193 					json("code", r.getCode()) }, ",") + "}").getBytes(ENCODING));
194 
195 			if (first) {
196 				first = false;
197 			}
198 		}
199 
200 		os.write("]".getBytes(ENCODING));
201 
202 		final Map<String, Map<String, String>> properties = appStatus.getProperties();
203 
204 		os.write((", \"properties\" : [").getBytes(ENCODING));
205 
206 		first = true;
207 		for (Entry<String, Map<String, String>> cat : properties.entrySet()) {
208 
209 			for (final Entry<String, String> r : cat.getValue().entrySet()) {
210 				if (!first) {
211 					os.write((",").getBytes(ENCODING));
212 				}
213 
214 				os.write(("{" + join(new String[] { json("group", cat.getKey()), json("name", r.getKey()),
215 						json("value", r.getValue()) }, ",") + "}").getBytes(ENCODING));
216 
217 				if (first) {
218 					first = false;
219 				}
220 			}
221 		}
222 
223 		os.write("]".getBytes(ENCODING));
224 
225 		os.write("}".getBytes(ENCODING));
226 
227 	}
228 
229 	@Override
230 	public void doPost(final StatusWebHandler webHandler, final HttpServletRequest req,
231 			final HttpServletResponse resp) {
232 		updateMode(webHandler, req.getParameter("mode"));
233 		try {
234 			resp.sendRedirect(req.getRequestURI());
235 		} catch (final IOException ex) {
236 			LOGGER.warn("Unable to redirect to main status page after updating mode", ex);
237 		}
238 	}
239 
240 	@Override
241 	public String getId() {
242 		return "status";
243 	}
244 
245 	@Override
246 	public String getName() {
247 		return "Status";
248 	}
249 
250 	private void updateMode(final StatusWebHandler webHandler, final String mode) {
251 		if (null != mode) {
252 			try {
253 				webHandler.getAppStatus().setMaintenance("maintenance".equalsIgnoreCase(mode));
254 			} catch (final IOException ex) {
255 				throw new RuntimeException("Error while updating maintenance status", ex);
256 			}
257 		}
258 	}
259 }