PageRenderTime 118ms CodeModel.GetById 7ms RepoModel.GetById 0ms app.codeStats 0ms

/javamelody-core/src/main/java/net/bull/javamelody/SerializableController.java

https://gitlab.com/tuandung.bui/javamelody
Java | 308 lines | 243 code | 20 blank | 45 comment | 60 complexity | 88624011c1f0c4e6be123348b3b4ca97 MD5 | raw file
  1. /*
  2. * Copyright 2008-2016 by Emeric Vernat
  3. *
  4. * This file is part of Java Melody.
  5. *
  6. * Licensed under the Apache License, Version 2.0 (the "License");
  7. * you may not use this file except in compliance with the License.
  8. * You may obtain a copy of the License at
  9. *
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing, software
  13. * distributed under the License is distributed on an "AS IS" BASIS,
  14. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. * See the License for the specific language governing permissions and
  16. * limitations under the License.
  17. */
  18. package net.bull.javamelody; // NOPMD
  19. import static net.bull.javamelody.HttpParameters.CONNECTIONS_PART;
  20. import static net.bull.javamelody.HttpParameters.CONTENT_DISPOSITION;
  21. import static net.bull.javamelody.HttpParameters.COUNTER_PARAMETER;
  22. import static net.bull.javamelody.HttpParameters.COUNTER_SUMMARY_PER_CLASS_PART;
  23. import static net.bull.javamelody.HttpParameters.CURRENT_REQUESTS_PART;
  24. import static net.bull.javamelody.HttpParameters.DATABASE_PART;
  25. import static net.bull.javamelody.HttpParameters.DEFAULT_WITH_CURRENT_REQUESTS_PART;
  26. import static net.bull.javamelody.HttpParameters.EXPLAIN_PLAN_PART;
  27. import static net.bull.javamelody.HttpParameters.FORMAT_PARAMETER;
  28. import static net.bull.javamelody.HttpParameters.GRAPH_PARAMETER;
  29. import static net.bull.javamelody.HttpParameters.GRAPH_PART;
  30. import static net.bull.javamelody.HttpParameters.HEAP_HISTO_PART;
  31. import static net.bull.javamelody.HttpParameters.HEIGHT_PARAMETER;
  32. import static net.bull.javamelody.HttpParameters.HOTSPOTS_PART;
  33. import static net.bull.javamelody.HttpParameters.JMX_VALUE;
  34. import static net.bull.javamelody.HttpParameters.JNDI_PART;
  35. import static net.bull.javamelody.HttpParameters.JROBINS_PART;
  36. import static net.bull.javamelody.HttpParameters.JVM_PART;
  37. import static net.bull.javamelody.HttpParameters.LAST_VALUE_PART;
  38. import static net.bull.javamelody.HttpParameters.MBEANS_PART;
  39. import static net.bull.javamelody.HttpParameters.OTHER_JROBINS_PART;
  40. import static net.bull.javamelody.HttpParameters.PART_PARAMETER;
  41. import static net.bull.javamelody.HttpParameters.PATH_PARAMETER;
  42. import static net.bull.javamelody.HttpParameters.PERIOD_PARAMETER;
  43. import static net.bull.javamelody.HttpParameters.PROCESSES_PART;
  44. import static net.bull.javamelody.HttpParameters.REQUEST_PARAMETER;
  45. import static net.bull.javamelody.HttpParameters.SESSIONS_PART;
  46. import static net.bull.javamelody.HttpParameters.SESSION_ID_PARAMETER;
  47. import static net.bull.javamelody.HttpParameters.THREADS_PART;
  48. import static net.bull.javamelody.HttpParameters.WIDTH_PARAMETER;
  49. import java.io.IOException;
  50. import java.io.Serializable;
  51. import java.util.ArrayList;
  52. import java.util.Collection;
  53. import java.util.HashMap;
  54. import java.util.LinkedHashMap;
  55. import java.util.List;
  56. import java.util.Map;
  57. import javax.servlet.http.HttpServletRequest;
  58. import javax.servlet.http.HttpServletResponse;
  59. import net.bull.javamelody.SamplingProfiler.SampledMethod;
  60. /**
  61. * Contrôleur au sens MVC pour la partie des données sérialisées.
  62. * @author Emeric Vernat
  63. */
  64. class SerializableController { // NOPMD
  65. private final Collector collector;
  66. SerializableController(Collector collector) {
  67. super();
  68. assert collector != null;
  69. this.collector = collector;
  70. }
  71. void doSerializable(HttpServletRequest httpRequest, HttpServletResponse httpResponse,
  72. Serializable serializable) throws IOException {
  73. // l'appelant (un serveur d'agrégation par exemple) peut appeler
  74. // la page monitoring avec un format "serialized" ou "xml" en paramètre
  75. // pour avoir les données au format sérialisé java ou xml
  76. final String format = httpRequest.getParameter(FORMAT_PARAMETER);
  77. final TransportFormat transportFormat = TransportFormat.valueOfIgnoreCase(format);
  78. // checkDependencies avant setContentType pour afficher correctement les erreurs
  79. transportFormat.checkDependencies();
  80. httpResponse.setContentType(transportFormat.getMimeType());
  81. final String fileName = "JavaMelody_" + getApplication().replace(' ', '_').replace("/", "")
  82. + '_' + I18N.getCurrentDate().replace('/', '_') + '.' + transportFormat.getCode();
  83. final String contentDisposition = "inline;filename=" + fileName;
  84. // encoding des CRLF pour http://en.wikipedia.org/wiki/HTTP_response_splitting
  85. httpResponse.addHeader(CONTENT_DISPOSITION,
  86. contentDisposition.replace('\n', '_').replace('\r', '_'));
  87. transportFormat.writeSerializableTo(serializable, httpResponse.getOutputStream());
  88. }
  89. // CHECKSTYLE:OFF
  90. Serializable createSerializable(HttpServletRequest httpRequest, // NOPMD
  91. List<JavaInformations> javaInformationsList, String messageForReport) throws Exception { // NOPMD
  92. // CHECKSTYLE:ON
  93. final String part = httpRequest.getParameter(PART_PARAMETER);
  94. if (JVM_PART.equalsIgnoreCase(part)) {
  95. return new ArrayList<JavaInformations>(javaInformationsList);
  96. } else if (SESSIONS_PART.equalsIgnoreCase(part)) {
  97. // par sécurité
  98. Action.checkSystemActionsEnabled();
  99. final String sessionId = httpRequest.getParameter(SESSION_ID_PARAMETER);
  100. if (sessionId == null) {
  101. return new ArrayList<SessionInformations>(
  102. SessionListener.getAllSessionsInformations());
  103. }
  104. return SessionListener.getSessionInformationsBySessionId(sessionId);
  105. } else if (HOTSPOTS_PART.equalsIgnoreCase(part)) {
  106. // par sécurité
  107. Action.checkSystemActionsEnabled();
  108. return new ArrayList<SampledMethod>(collector.getHotspots());
  109. } else if (HEAP_HISTO_PART.equalsIgnoreCase(part)) {
  110. // par sécurité
  111. Action.checkSystemActionsEnabled();
  112. return VirtualMachine.createHeapHistogram();
  113. } else if (PROCESSES_PART.equalsIgnoreCase(part)) {
  114. // par sécurité
  115. Action.checkSystemActionsEnabled();
  116. return new ArrayList<ProcessInformations>(
  117. ProcessInformations.buildProcessInformations());
  118. } else if (JNDI_PART.equalsIgnoreCase(part)) {
  119. // par sécurité
  120. Action.checkSystemActionsEnabled();
  121. final String path = httpRequest.getParameter(PATH_PARAMETER);
  122. return new ArrayList<JndiBinding>(JndiBinding.listBindings(path));
  123. } else if (MBEANS_PART.equalsIgnoreCase(part)) {
  124. // par sécurité
  125. Action.checkSystemActionsEnabled();
  126. return new ArrayList<MBeanNode>(MBeans.getAllMBeanNodes());
  127. } else if (httpRequest.getParameter(JMX_VALUE) != null) {
  128. // par sécurité
  129. Action.checkSystemActionsEnabled();
  130. final String jmxValue = httpRequest.getParameter(JMX_VALUE);
  131. return MBeans.getConvertedAttributes(jmxValue);
  132. } else if (LAST_VALUE_PART.equalsIgnoreCase(part)) {
  133. final String graph = httpRequest.getParameter(GRAPH_PARAMETER);
  134. final JRobin jrobin = collector.getJRobin(graph);
  135. final double lastValue;
  136. if (jrobin == null) {
  137. lastValue = -1;
  138. } else {
  139. lastValue = jrobin.getLastValue();
  140. }
  141. return lastValue;
  142. } else if (DATABASE_PART.equalsIgnoreCase(part)) {
  143. // par sécurité
  144. Action.checkSystemActionsEnabled();
  145. final int requestIndex = DatabaseInformations
  146. .parseRequestIndex(httpRequest.getParameter(REQUEST_PARAMETER));
  147. return new DatabaseInformations(requestIndex);
  148. } else if (CONNECTIONS_PART.equalsIgnoreCase(part)) {
  149. // par sécurité
  150. Action.checkSystemActionsEnabled();
  151. return new ArrayList<ConnectionInformations>(
  152. JdbcWrapper.getConnectionInformationsList());
  153. }
  154. return createOtherSerializable(httpRequest, javaInformationsList, messageForReport);
  155. }
  156. @SuppressWarnings("unchecked")
  157. private Serializable createOtherSerializable(HttpServletRequest httpRequest,
  158. List<JavaInformations> javaInformationsList, String messageForReport)
  159. throws IOException {
  160. final Range range = getRangeForSerializable(httpRequest);
  161. final String part = httpRequest.getParameter(PART_PARAMETER);
  162. if (JROBINS_PART.equalsIgnoreCase(part)) {
  163. // pour UI Swing
  164. final int width = Integer.parseInt(httpRequest.getParameter(WIDTH_PARAMETER));
  165. final int height = Integer.parseInt(httpRequest.getParameter(HEIGHT_PARAMETER));
  166. final String graphName = httpRequest.getParameter(GRAPH_PARAMETER);
  167. return getJRobinsImages(range, width, height, graphName);
  168. } else if (OTHER_JROBINS_PART.equalsIgnoreCase(part)) {
  169. // pour UI Swing
  170. final int width = Integer.parseInt(httpRequest.getParameter(WIDTH_PARAMETER));
  171. final int height = Integer.parseInt(httpRequest.getParameter(HEIGHT_PARAMETER));
  172. final Collection<JRobin> jrobins = collector.getDisplayedOtherJRobins();
  173. return (Serializable) convertJRobinsToImages(jrobins, range, width, height);
  174. } else if (THREADS_PART.equalsIgnoreCase(part)) {
  175. return new ArrayList<ThreadInformations>(
  176. javaInformationsList.get(0).getThreadInformationsList());
  177. } else if (COUNTER_SUMMARY_PER_CLASS_PART.equalsIgnoreCase(part)) {
  178. final String counterName = httpRequest.getParameter(COUNTER_PARAMETER);
  179. final String requestId = httpRequest.getParameter(GRAPH_PARAMETER);
  180. final Counter counter = collector.getRangeCounter(range, counterName).clone();
  181. final List<CounterRequest> requestList = new CounterRequestAggregation(counter)
  182. .getRequestsAggregatedOrFilteredByClassName(requestId);
  183. return new ArrayList<CounterRequest>(requestList);
  184. } else if (GRAPH_PART.equalsIgnoreCase(part)) {
  185. final String requestId = httpRequest.getParameter(GRAPH_PARAMETER);
  186. return getCounterRequestById(requestId, range);
  187. } else if (CURRENT_REQUESTS_PART.equalsIgnoreCase(part)) {
  188. final Map<JavaInformations, List<CounterRequestContext>> result = new HashMap<JavaInformations, List<CounterRequestContext>>();
  189. result.put(javaInformationsList.get(0), getCurrentRequests());
  190. return (Serializable) result;
  191. } else if (DEFAULT_WITH_CURRENT_REQUESTS_PART.equalsIgnoreCase(part)) {
  192. final List<Serializable> result = new ArrayList<Serializable>();
  193. result.addAll((List<Serializable>) createDefaultSerializable(javaInformationsList,
  194. range, messageForReport));
  195. result.addAll(getCurrentRequests());
  196. return (Serializable) result;
  197. } else if (EXPLAIN_PLAN_PART.equalsIgnoreCase(part)) {
  198. // pour UI Swing,
  199. final String sqlRequest = httpRequest.getHeader(REQUEST_PARAMETER);
  200. return explainPlanFor(sqlRequest);
  201. }
  202. return createDefaultSerializable(javaInformationsList, range, messageForReport);
  203. }
  204. private Serializable getCounterRequestById(String requestId, Range range) throws IOException {
  205. for (final Counter counter : collector.getCounters()) {
  206. if (counter.isRequestIdFromThisCounter(requestId)) {
  207. final Counter rangeCounter = collector.getRangeCounter(range, counter.getName())
  208. .clone();
  209. for (final CounterRequest request : rangeCounter.getRequests()) {
  210. if (requestId.equals(request.getId())) {
  211. return request;
  212. }
  213. }
  214. }
  215. }
  216. // non trouvé
  217. return null;
  218. }
  219. private Serializable getJRobinsImages(Range range, int width, int height, String graphName)
  220. throws IOException {
  221. if (graphName != null) {
  222. final JRobin jrobin = collector.getJRobin(graphName);
  223. if (jrobin != null) {
  224. return jrobin.graph(range, width, height);
  225. }
  226. return null;
  227. }
  228. final Collection<JRobin> jrobins = collector.getDisplayedCounterJRobins();
  229. return (Serializable) convertJRobinsToImages(jrobins, range, width, height);
  230. }
  231. private Serializable explainPlanFor(String sqlRequest) {
  232. assert sqlRequest != null;
  233. try {
  234. // retourne le plan d'exécution ou null si la base de données ne le permet pas (ie non Oracle)
  235. return DatabaseInformations.explainPlanFor(sqlRequest);
  236. } catch (final Exception ex) {
  237. return ex.toString();
  238. }
  239. }
  240. private List<CounterRequestContext> getCurrentRequests() {
  241. final List<Counter> counters = collector.getCounters();
  242. final List<Counter> newCounters = new ArrayList<Counter>();
  243. for (final Counter counter : counters) {
  244. final Counter cloneLight = new Counter(counter.getName(), counter.getStorageName(),
  245. counter.getIconName(), counter.getChildCounterName());
  246. newCounters.add(cloneLight);
  247. }
  248. // note: ces contextes ont été clonés dans getRootCurrentContexts(newCounters) par getOrderedRootCurrentContexts()
  249. return collector.getRootCurrentContexts(newCounters);
  250. }
  251. private Map<String, byte[]> convertJRobinsToImages(Collection<JRobin> jrobins, Range range,
  252. int width, int height) throws IOException {
  253. final Map<String, byte[]> images = new LinkedHashMap<String, byte[]>(jrobins.size());
  254. for (final JRobin jrobin : jrobins) {
  255. final byte[] image = jrobin.graph(range, width, height);
  256. images.put(jrobin.getName(), image);
  257. }
  258. return images;
  259. }
  260. Serializable createDefaultSerializable(List<JavaInformations> javaInformationsList, Range range,
  261. String messageForReport) throws IOException {
  262. final List<Counter> counters = collector.getRangeCounters(range);
  263. final List<Serializable> serialized = new ArrayList<Serializable>(
  264. counters.size() + javaInformationsList.size());
  265. // on clone les counters avant de les sérialiser pour ne pas avoir de problèmes de concurrences d'accès
  266. for (final Counter counter : counters) {
  267. serialized.add(counter.clone());
  268. }
  269. serialized.addAll(javaInformationsList);
  270. if (messageForReport != null) {
  271. serialized.add(messageForReport);
  272. }
  273. return (Serializable) serialized;
  274. }
  275. Range getRangeForSerializable(HttpServletRequest httpRequest) {
  276. final Range range;
  277. if (httpRequest.getParameter(PERIOD_PARAMETER) == null) {
  278. // période tout par défaut pour Serializable, notamment pour le serveur de collecte
  279. range = Period.TOUT.getRange();
  280. } else {
  281. range = Range.parse(httpRequest.getParameter(PERIOD_PARAMETER));
  282. }
  283. return range;
  284. }
  285. private String getApplication() {
  286. return collector.getApplication();
  287. }
  288. }