org.apache.sling.reqanalyzer.impl.RequestAnalyzerWebConsole.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.sling.reqanalyzer.impl.RequestAnalyzerWebConsole.java

Source

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 org.apache.sling.reqanalyzer.impl;

import java.awt.AWTEvent;
import java.awt.Dimension;
import java.awt.GraphicsEnvironment;
import java.awt.Toolkit;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Date;
import java.util.zip.Deflater;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.io.IOUtils;
import org.apache.sling.reqanalyzer.impl.gui.MainFrame;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@SuppressWarnings("serial")
public class RequestAnalyzerWebConsole extends HttpServlet {

    private static final String WINDOW_MARKER = ".showWindow";

    private static final String RAW_FILE_MARKER = ".txt";

    private static final String ZIP_FILE_MARKER = ".txt.zip";

    /** default log */
    private final Logger log = LoggerFactory.getLogger(getClass());

    private final File logFile;

    private MainFrame frame;

    RequestAnalyzerWebConsole(final File logFile) {
        this.logFile = logFile;
    }

    void dispose() {
        if (this.frame != null) {
            MainFrame frame = this.frame;
            this.frame = null;
            AWTEvent e = new WindowEvent(frame, WindowEvent.WINDOW_CLOSING);
            Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(e);
        }
    }

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        if (req.getRequestURI().endsWith(RAW_FILE_MARKER) || req.getRequestURI().endsWith(ZIP_FILE_MARKER)) {

            InputStream input = null;
            OutputStream output = null;
            try {
                input = new FileInputStream(this.logFile);
                output = resp.getOutputStream();

                if (req.getRequestURI().endsWith(ZIP_FILE_MARKER)) {
                    ZipOutputStream zip = new ZipOutputStream(output);
                    zip.setLevel(Deflater.BEST_SPEED);

                    ZipEntry entry = new ZipEntry(this.logFile.getName());
                    entry.setTime(this.logFile.lastModified());
                    entry.setMethod(ZipEntry.DEFLATED);

                    zip.putNextEntry(entry);

                    output = zip;
                    resp.setContentType("application/zip");
                } else {
                    resp.setContentType("text/plain");
                    resp.setCharacterEncoding("UTF-8");
                    resp.setHeader("Content-Length", String.valueOf(this.logFile.length())); // might be bigger than
                }
                resp.setDateHeader("Last-Modified", this.logFile.lastModified());

                IOUtils.copy(input, output);
            } catch (IOException ioe) {
                throw new ServletException("Cannot create copy of log file", ioe);
            } finally {
                IOUtils.closeQuietly(input);

                if (output instanceof ZipOutputStream) {
                    ((ZipOutputStream) output).closeEntry();
                    ((ZipOutputStream) output).finish();
                }
            }

            resp.flushBuffer();

        } else if (req.getRequestURI().endsWith(WINDOW_MARKER)) {

            if (canOpenSwingGui(req)) {
                showWindow();
            }

            String target = req.getRequestURI();
            target = target.substring(0, target.length() - WINDOW_MARKER.length());
            resp.sendRedirect(target);
            resp.flushBuffer();

        } else {

            super.service(req, resp);

        }
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        PrintWriter pw = resp.getWriter();

        final String fileSize = this.formatByteSize(this.logFile.length());
        pw.printf("<p class='statline ui-state-highlight'>Request Log Size %s</p>%n", fileSize);

        pw.println("<table class='nicetable ui-widget'>");
        pw.println("  <thead>");
        pw.println("    <tr>");
        pw.println("        <th class='ui-widget-header'>Name</th>");
        pw.println("        <th class='ui-widget-header'>Last Update</th>");
        pw.println("        <th class='ui-widget-header'>Size</th>");
        pw.println("        <th class='ui-widget-header'>Action</th>");
        pw.println("    </tr>");
        pw.println("</thead>");
        pw.println("<tbody>");

        pw.println("<tr>");

        pw.printf("<td><a href='${pluginRoot}%s'>%s</a> (<a href='${pluginRoot}%s'>zipped</a>)</td>%n",
                RAW_FILE_MARKER, this.logFile.getName(), ZIP_FILE_MARKER);
        pw.printf("<td>%s</td><td>%s</td>", new Date(this.logFile.lastModified()), fileSize);

        pw.println("<td><ul class='icons ui-widget'>");
        if (canOpenSwingGui(req)) {
            pw.printf(
                    "<li title='Analyze Now' class='dynhover ui-state-default ui-corner-all'><a href='${pluginRoot}%s'><span class='ui-icon ui-icon-wrench'></span></a></li>%n",
                    WINDOW_MARKER);
            // pw.printf(" (<a href='${pluginRoot}%s'>Analyze Now</a>)", WINDOW_MARKER);
        }
        // pw.println("<li title='Remove File' class='dynhover ui-state-default ui-corner-all'><span class='ui-icon ui-icon-trash'></span></li>");
        pw.println("</ul></td>");

        pw.println("</tr></tbody>");
        pw.println("</table>");

    }

    private synchronized void showWindow() throws ServletException, IOException {
        if (this.frame == null) {
            final File toAnalyze = this.getLogFileCopy();

            final Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
            MainFrame frame = new MainFrame(toAnalyze, Integer.MAX_VALUE, screenSize);

            // exit the application if the main frame is closed
            frame.addWindowListener(new WindowAdapter() {
                @Override
                public void windowClosing(WindowEvent e) {
                    // remove the tmp file we showed
                    if (toAnalyze.exists()) {
                        toAnalyze.delete();
                    }
                    // clear the window reference
                    RequestAnalyzerWebConsole.this.frame = null;
                }
            });

            this.frame = frame;
        }

        // make sure the window is visible, try to bring to the front
        this.frame.setVisible(true);
        this.frame.toFront();
    }

    private boolean canOpenSwingGui(final ServletRequest request) {
        try {
            return !GraphicsEnvironment.isHeadless()
                    && InetAddress.getByName(request.getLocalAddr()).isLoopbackAddress();
        } catch (UnknownHostException e) {
            // unexpected, but still fall back to fail-safe false
            return false;
        }
    }

    private final File getLogFileCopy() throws ServletException {
        File result = null;
        InputStream input = null;
        OutputStream output = null;
        try {
            result = File.createTempFile(getServletName(), ".tmp");
            input = new FileInputStream(this.logFile);
            output = new FileOutputStream(result);
            IOUtils.copy(input, output);
            return result;
        } catch (IOException ioe) {
            throw new ServletException("Cannot create copy of log file", ioe);
        } finally {
            IOUtils.closeQuietly(input);
            IOUtils.closeQuietly(output);
        }
    }

    private String formatByteSize(final long value) {
        final String suffix;
        final String suffixedValue;

        if (value >= 0) {
            final BigDecimal KB = new BigDecimal(1000L);
            final BigDecimal MB = new BigDecimal(1000L * 1000);
            final BigDecimal GB = new BigDecimal(1000L * 1000 * 1000);

            BigDecimal bd = new BigDecimal(value);
            if (bd.compareTo(GB) > 0) {
                bd = bd.divide(GB);
                suffix = "GB";
            } else if (bd.compareTo(MB) > 0) {
                bd = bd.divide(MB);
                suffix = "MB";
            } else if (bd.compareTo(KB) > 0) {
                bd = bd.divide(KB);
                suffix = "kB";
            } else {
                suffix = "B";
            }
            suffixedValue = bd.setScale(2, RoundingMode.UP).toString();
        } else {
            suffixedValue = "n/a";
            suffix = "";
        }

        return suffixedValue + suffix;
    }

}