/javamelody-core/src/main/java/net/bull/javamelody/SerializableController.java
Java | 308 lines | 243 code | 20 blank | 45 comment | 60 complexity | 88624011c1f0c4e6be123348b3b4ca97 MD5 | raw file
- /*
- * Copyright 2008-2016 by Emeric Vernat
- *
- * This file is part of Java Melody.
- *
- * 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.
- */
- package net.bull.javamelody; // NOPMD
-
- import static net.bull.javamelody.HttpParameters.CONNECTIONS_PART;
- import static net.bull.javamelody.HttpParameters.CONTENT_DISPOSITION;
- import static net.bull.javamelody.HttpParameters.COUNTER_PARAMETER;
- import static net.bull.javamelody.HttpParameters.COUNTER_SUMMARY_PER_CLASS_PART;
- import static net.bull.javamelody.HttpParameters.CURRENT_REQUESTS_PART;
- import static net.bull.javamelody.HttpParameters.DATABASE_PART;
- import static net.bull.javamelody.HttpParameters.DEFAULT_WITH_CURRENT_REQUESTS_PART;
- import static net.bull.javamelody.HttpParameters.EXPLAIN_PLAN_PART;
- import static net.bull.javamelody.HttpParameters.FORMAT_PARAMETER;
- import static net.bull.javamelody.HttpParameters.GRAPH_PARAMETER;
- import static net.bull.javamelody.HttpParameters.GRAPH_PART;
- import static net.bull.javamelody.HttpParameters.HEAP_HISTO_PART;
- import static net.bull.javamelody.HttpParameters.HEIGHT_PARAMETER;
- import static net.bull.javamelody.HttpParameters.HOTSPOTS_PART;
- import static net.bull.javamelody.HttpParameters.JMX_VALUE;
- import static net.bull.javamelody.HttpParameters.JNDI_PART;
- import static net.bull.javamelody.HttpParameters.JROBINS_PART;
- import static net.bull.javamelody.HttpParameters.JVM_PART;
- import static net.bull.javamelody.HttpParameters.LAST_VALUE_PART;
- import static net.bull.javamelody.HttpParameters.MBEANS_PART;
- import static net.bull.javamelody.HttpParameters.OTHER_JROBINS_PART;
- import static net.bull.javamelody.HttpParameters.PART_PARAMETER;
- import static net.bull.javamelody.HttpParameters.PATH_PARAMETER;
- import static net.bull.javamelody.HttpParameters.PERIOD_PARAMETER;
- import static net.bull.javamelody.HttpParameters.PROCESSES_PART;
- import static net.bull.javamelody.HttpParameters.REQUEST_PARAMETER;
- import static net.bull.javamelody.HttpParameters.SESSIONS_PART;
- import static net.bull.javamelody.HttpParameters.SESSION_ID_PARAMETER;
- import static net.bull.javamelody.HttpParameters.THREADS_PART;
- import static net.bull.javamelody.HttpParameters.WIDTH_PARAMETER;
-
- import java.io.IOException;
- import java.io.Serializable;
- import java.util.ArrayList;
- import java.util.Collection;
- import java.util.HashMap;
- import java.util.LinkedHashMap;
- import java.util.List;
- import java.util.Map;
-
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
-
- import net.bull.javamelody.SamplingProfiler.SampledMethod;
-
- /**
- * Contrôleur au sens MVC pour la partie des données sérialisées.
- * @author Emeric Vernat
- */
- class SerializableController { // NOPMD
- private final Collector collector;
-
- SerializableController(Collector collector) {
- super();
- assert collector != null;
- this.collector = collector;
- }
-
- void doSerializable(HttpServletRequest httpRequest, HttpServletResponse httpResponse,
- Serializable serializable) throws IOException {
- // l'appelant (un serveur d'agrégation par exemple) peut appeler
- // la page monitoring avec un format "serialized" ou "xml" en paramètre
- // pour avoir les données au format sérialisé java ou xml
- final String format = httpRequest.getParameter(FORMAT_PARAMETER);
- final TransportFormat transportFormat = TransportFormat.valueOfIgnoreCase(format);
- // checkDependencies avant setContentType pour afficher correctement les erreurs
- transportFormat.checkDependencies();
- httpResponse.setContentType(transportFormat.getMimeType());
- final String fileName = "JavaMelody_" + getApplication().replace(' ', '_').replace("/", "")
- + '_' + I18N.getCurrentDate().replace('/', '_') + '.' + transportFormat.getCode();
- final String contentDisposition = "inline;filename=" + fileName;
- // encoding des CRLF pour http://en.wikipedia.org/wiki/HTTP_response_splitting
- httpResponse.addHeader(CONTENT_DISPOSITION,
- contentDisposition.replace('\n', '_').replace('\r', '_'));
-
- transportFormat.writeSerializableTo(serializable, httpResponse.getOutputStream());
- }
-
- // CHECKSTYLE:OFF
- Serializable createSerializable(HttpServletRequest httpRequest, // NOPMD
- List<JavaInformations> javaInformationsList, String messageForReport) throws Exception { // NOPMD
- // CHECKSTYLE:ON
- final String part = httpRequest.getParameter(PART_PARAMETER);
- if (JVM_PART.equalsIgnoreCase(part)) {
- return new ArrayList<JavaInformations>(javaInformationsList);
- } else if (SESSIONS_PART.equalsIgnoreCase(part)) {
- // par sécurité
- Action.checkSystemActionsEnabled();
- final String sessionId = httpRequest.getParameter(SESSION_ID_PARAMETER);
- if (sessionId == null) {
- return new ArrayList<SessionInformations>(
- SessionListener.getAllSessionsInformations());
- }
- return SessionListener.getSessionInformationsBySessionId(sessionId);
- } else if (HOTSPOTS_PART.equalsIgnoreCase(part)) {
- // par sécurité
- Action.checkSystemActionsEnabled();
- return new ArrayList<SampledMethod>(collector.getHotspots());
- } else if (HEAP_HISTO_PART.equalsIgnoreCase(part)) {
- // par sécurité
- Action.checkSystemActionsEnabled();
- return VirtualMachine.createHeapHistogram();
- } else if (PROCESSES_PART.equalsIgnoreCase(part)) {
- // par sécurité
- Action.checkSystemActionsEnabled();
- return new ArrayList<ProcessInformations>(
- ProcessInformations.buildProcessInformations());
- } else if (JNDI_PART.equalsIgnoreCase(part)) {
- // par sécurité
- Action.checkSystemActionsEnabled();
- final String path = httpRequest.getParameter(PATH_PARAMETER);
- return new ArrayList<JndiBinding>(JndiBinding.listBindings(path));
- } else if (MBEANS_PART.equalsIgnoreCase(part)) {
- // par sécurité
- Action.checkSystemActionsEnabled();
- return new ArrayList<MBeanNode>(MBeans.getAllMBeanNodes());
- } else if (httpRequest.getParameter(JMX_VALUE) != null) {
- // par sécurité
- Action.checkSystemActionsEnabled();
- final String jmxValue = httpRequest.getParameter(JMX_VALUE);
- return MBeans.getConvertedAttributes(jmxValue);
- } else if (LAST_VALUE_PART.equalsIgnoreCase(part)) {
- final String graph = httpRequest.getParameter(GRAPH_PARAMETER);
- final JRobin jrobin = collector.getJRobin(graph);
- final double lastValue;
- if (jrobin == null) {
- lastValue = -1;
- } else {
- lastValue = jrobin.getLastValue();
- }
- return lastValue;
- } else if (DATABASE_PART.equalsIgnoreCase(part)) {
- // par sécurité
- Action.checkSystemActionsEnabled();
- final int requestIndex = DatabaseInformations
- .parseRequestIndex(httpRequest.getParameter(REQUEST_PARAMETER));
- return new DatabaseInformations(requestIndex);
- } else if (CONNECTIONS_PART.equalsIgnoreCase(part)) {
- // par sécurité
- Action.checkSystemActionsEnabled();
- return new ArrayList<ConnectionInformations>(
- JdbcWrapper.getConnectionInformationsList());
- }
- return createOtherSerializable(httpRequest, javaInformationsList, messageForReport);
- }
-
- @SuppressWarnings("unchecked")
- private Serializable createOtherSerializable(HttpServletRequest httpRequest,
- List<JavaInformations> javaInformationsList, String messageForReport)
- throws IOException {
- final Range range = getRangeForSerializable(httpRequest);
- final String part = httpRequest.getParameter(PART_PARAMETER);
- if (JROBINS_PART.equalsIgnoreCase(part)) {
- // pour UI Swing
- final int width = Integer.parseInt(httpRequest.getParameter(WIDTH_PARAMETER));
- final int height = Integer.parseInt(httpRequest.getParameter(HEIGHT_PARAMETER));
- final String graphName = httpRequest.getParameter(GRAPH_PARAMETER);
- return getJRobinsImages(range, width, height, graphName);
- } else if (OTHER_JROBINS_PART.equalsIgnoreCase(part)) {
- // pour UI Swing
- final int width = Integer.parseInt(httpRequest.getParameter(WIDTH_PARAMETER));
- final int height = Integer.parseInt(httpRequest.getParameter(HEIGHT_PARAMETER));
- final Collection<JRobin> jrobins = collector.getDisplayedOtherJRobins();
- return (Serializable) convertJRobinsToImages(jrobins, range, width, height);
- } else if (THREADS_PART.equalsIgnoreCase(part)) {
- return new ArrayList<ThreadInformations>(
- javaInformationsList.get(0).getThreadInformationsList());
- } else if (COUNTER_SUMMARY_PER_CLASS_PART.equalsIgnoreCase(part)) {
- final String counterName = httpRequest.getParameter(COUNTER_PARAMETER);
- final String requestId = httpRequest.getParameter(GRAPH_PARAMETER);
- final Counter counter = collector.getRangeCounter(range, counterName).clone();
- final List<CounterRequest> requestList = new CounterRequestAggregation(counter)
- .getRequestsAggregatedOrFilteredByClassName(requestId);
- return new ArrayList<CounterRequest>(requestList);
- } else if (GRAPH_PART.equalsIgnoreCase(part)) {
- final String requestId = httpRequest.getParameter(GRAPH_PARAMETER);
- return getCounterRequestById(requestId, range);
- } else if (CURRENT_REQUESTS_PART.equalsIgnoreCase(part)) {
- final Map<JavaInformations, List<CounterRequestContext>> result = new HashMap<JavaInformations, List<CounterRequestContext>>();
- result.put(javaInformationsList.get(0), getCurrentRequests());
- return (Serializable) result;
- } else if (DEFAULT_WITH_CURRENT_REQUESTS_PART.equalsIgnoreCase(part)) {
- final List<Serializable> result = new ArrayList<Serializable>();
- result.addAll((List<Serializable>) createDefaultSerializable(javaInformationsList,
- range, messageForReport));
- result.addAll(getCurrentRequests());
- return (Serializable) result;
- } else if (EXPLAIN_PLAN_PART.equalsIgnoreCase(part)) {
- // pour UI Swing,
- final String sqlRequest = httpRequest.getHeader(REQUEST_PARAMETER);
- return explainPlanFor(sqlRequest);
- }
-
- return createDefaultSerializable(javaInformationsList, range, messageForReport);
- }
-
- private Serializable getCounterRequestById(String requestId, Range range) throws IOException {
- for (final Counter counter : collector.getCounters()) {
- if (counter.isRequestIdFromThisCounter(requestId)) {
- final Counter rangeCounter = collector.getRangeCounter(range, counter.getName())
- .clone();
- for (final CounterRequest request : rangeCounter.getRequests()) {
- if (requestId.equals(request.getId())) {
- return request;
- }
- }
- }
- }
- // non trouvé
- return null;
- }
-
- private Serializable getJRobinsImages(Range range, int width, int height, String graphName)
- throws IOException {
- if (graphName != null) {
- final JRobin jrobin = collector.getJRobin(graphName);
- if (jrobin != null) {
- return jrobin.graph(range, width, height);
- }
- return null;
- }
- final Collection<JRobin> jrobins = collector.getDisplayedCounterJRobins();
- return (Serializable) convertJRobinsToImages(jrobins, range, width, height);
- }
-
- private Serializable explainPlanFor(String sqlRequest) {
- assert sqlRequest != null;
- try {
- // retourne le plan d'exécution ou null si la base de données ne le permet pas (ie non Oracle)
- return DatabaseInformations.explainPlanFor(sqlRequest);
- } catch (final Exception ex) {
- return ex.toString();
- }
- }
-
- private List<CounterRequestContext> getCurrentRequests() {
- final List<Counter> counters = collector.getCounters();
- final List<Counter> newCounters = new ArrayList<Counter>();
- for (final Counter counter : counters) {
- final Counter cloneLight = new Counter(counter.getName(), counter.getStorageName(),
- counter.getIconName(), counter.getChildCounterName());
- newCounters.add(cloneLight);
- }
-
- // note: ces contextes ont été clonés dans getRootCurrentContexts(newCounters) par getOrderedRootCurrentContexts()
- return collector.getRootCurrentContexts(newCounters);
- }
-
- private Map<String, byte[]> convertJRobinsToImages(Collection<JRobin> jrobins, Range range,
- int width, int height) throws IOException {
- final Map<String, byte[]> images = new LinkedHashMap<String, byte[]>(jrobins.size());
- for (final JRobin jrobin : jrobins) {
- final byte[] image = jrobin.graph(range, width, height);
- images.put(jrobin.getName(), image);
- }
- return images;
- }
-
- Serializable createDefaultSerializable(List<JavaInformations> javaInformationsList, Range range,
- String messageForReport) throws IOException {
- final List<Counter> counters = collector.getRangeCounters(range);
- final List<Serializable> serialized = new ArrayList<Serializable>(
- counters.size() + javaInformationsList.size());
- // on clone les counters avant de les sérialiser pour ne pas avoir de problèmes de concurrences d'accès
- for (final Counter counter : counters) {
- serialized.add(counter.clone());
- }
- serialized.addAll(javaInformationsList);
- if (messageForReport != null) {
- serialized.add(messageForReport);
- }
- return (Serializable) serialized;
- }
-
- Range getRangeForSerializable(HttpServletRequest httpRequest) {
- final Range range;
- if (httpRequest.getParameter(PERIOD_PARAMETER) == null) {
- // période tout par défaut pour Serializable, notamment pour le serveur de collecte
- range = Period.TOUT.getRange();
- } else {
- range = Range.parse(httpRequest.getParameter(PERIOD_PARAMETER));
- }
- return range;
- }
-
- private String getApplication() {
- return collector.getApplication();
- }
- }