001/*
002 * (C) Copyright 2012-2013 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 */
017package org.nuxeo.connect.tools.report.viewer;
018
019import java.io.IOException;
020import java.io.InputStream;
021import java.io.PrintStream;
022import java.nio.file.Files;
023import java.nio.file.Paths;
024import java.util.Arrays;
025
026import org.apache.commons.cli.CommandLine;
027import org.apache.commons.cli.DefaultParser;
028import org.apache.commons.cli.Option;
029import org.apache.commons.cli.Options;
030import org.apache.commons.cli.ParseException;
031
032import com.fasterxml.jackson.core.JsonFactory;
033import com.fasterxml.jackson.core.JsonParser;
034import com.fasterxml.jackson.core.JsonToken;
035import com.fasterxml.jackson.databind.MappingIterator;
036import com.fasterxml.jackson.databind.ObjectMapper;
037import com.fasterxml.jackson.databind.node.ArrayNode;
038
039/**
040 * Prints a report in an human friendly way.
041 *
042 *
043 * @since 8.4
044 *
045 */
046public class Viewer {
047
048    public static void main(String[] varargs) throws IOException, ParseException {
049
050        class Arguments {
051            Options options = new Options()
052                    .addOption(Option.builder("i").longOpt("input").hasArg().argName("file").desc("report input file").build())
053                    .addOption(Option.builder("o").longOpt("output").hasArg().argName("file").desc("thread dump output file").build());
054            final CommandLine commandline = new DefaultParser().parse(options, varargs);
055
056            Arguments() throws ParseException {
057
058            }
059
060            InputStream input() throws IOException {
061                if (!commandline.hasOption('i')) {
062                    return System.in;
063                }
064                return Files.newInputStream(Paths.get(commandline.getOptionValue('i')));
065            }
066
067            PrintStream output() throws IOException {
068                if (!commandline.hasOption('o')) {
069                    return System.out;
070                }
071                return new PrintStream(commandline.getOptionValue('o'));
072            }
073
074        }
075
076        Arguments arguments = new Arguments();
077        final JsonFactory jsonFactory = new JsonFactory();
078        PrintStream output = arguments.output();
079        JsonParser parser = jsonFactory.createParser(arguments.input());
080        ObjectMapper mapper = new ObjectMapper();
081        while (!parser.isClosed() && parser.nextToken() != JsonToken.NOT_AVAILABLE) {
082            String hostid = parser.nextFieldName();
083            output.println(hostid);
084            {
085                parser.nextToken();
086                while (parser.nextToken() == JsonToken.FIELD_NAME) {
087                    if ("mx-thread-dump".equals(parser.getCurrentName())) {
088                        parser.nextToken(); // start mx-thread-dump report
089                        while (parser.nextToken() == JsonToken.FIELD_NAME) {
090                            if ("value".equals(parser.getCurrentName())) {
091                                parser.nextToken();
092                                printThreadDump(mapper.readTree(parser), output);
093                            } else {
094                                parser.nextToken();
095                                parser.skipChildren();
096                            }
097                        }
098                    } else if ("mx-thread-deadlocked".equals(parser.getCurrentName())) {
099                        parser.nextToken();
100                        while (parser.nextToken() == JsonToken.FIELD_NAME) {
101                            if ("value".equals(parser.getCurrentName())) {
102                                if (parser.nextToken() == JsonToken.START_ARRAY) {
103                                    printThreadDeadlocked(mapper.readerFor(Long.class).readValue(parser), output);
104                                }
105                            } else {
106                                parser.nextToken();
107                                parser.skipChildren();
108                            }
109                        }
110                    } else if ("mx-thread-monitor-deadlocked".equals(parser.getCurrentName())) {
111                        parser.nextToken();
112                        while (parser.nextToken() == JsonToken.FIELD_NAME) {
113                            if ("value".equals(parser.getCurrentName())) {
114                                if (parser.nextToken() == JsonToken.START_ARRAY) {
115                                    printThreadMonitorDeadlocked(mapper.readerFor(Long.class).readValues(parser), output);
116                                }
117                            } else {
118                                parser.nextToken();
119                                parser.skipChildren();
120                            }
121                        }
122                    } else {
123                        parser.nextToken();
124                        parser.skipChildren();
125                    }
126                }
127            }
128        }
129
130    }
131
132    public static PrintStream printThreadDump(ArrayNode infos, PrintStream out) throws IOException {
133        StringBuilder sb = new StringBuilder();
134        new ThreadDumpPrinter(infos).print(sb);
135        out.print(sb.toString());
136        return out;
137    }
138
139    public static PrintStream printThreadDeadlocked(MappingIterator<Long> values, PrintStream out) throws IOException {
140        out.print("deadlocked " + Arrays.toString(values.readAll().toArray()));
141        return out;
142    }
143
144    public static PrintStream printThreadMonitorDeadlocked(MappingIterator<Long> values, PrintStream out) throws IOException {
145        out.print("monitor deadlocked " + Arrays.toString(values.readAll().toArray()));
146        return out;
147    }
148
149}