This is an automated email from the ASF dual-hosted git repository.

rombert pushed a commit to branch master
in repository 
https://gitbox.apache.org/repos/asf/sling-org-apache-sling-reqanalyzer.git

commit a8510744e9025405e01c19b5c80ba707e99fdbb6
Author: Felix Meschberger <[email protected]>
AuthorDate: Tue Sep 24 07:58:42 2013 +0000

    SLING-3099 Expose the request analyzer log file through the Web Console
    
    - Allow for plain text download
    - Allow for zipped download
    - Support launching the Swing GUI
    
    git-svn-id: https://svn.apache.org/repos/asf/sling/trunk@1525810 
13f79535-47bb-0310-9956-ffa450edef68
---
 pom.xml                                            |   6 +
 .../reqanalyzer/impl/RequestAnalysisLogger.java    |  31 ++-
 .../impl/RequestAnalyzerWebConsole.java            | 250 +++++++++++++++++++++
 .../apache/sling/reqanalyzer/impl/gui/Main.java    |  10 +
 .../sling/reqanalyzer/impl/gui/MainFrame.java      |  12 +-
 5 files changed, 295 insertions(+), 14 deletions(-)

diff --git a/pom.xml b/pom.xml
index 55be5ec..265702f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -132,6 +132,12 @@
             <artifactId>slf4j-simple</artifactId>
         </dependency>
         <dependency>
+            <groupId>commons-io</groupId>
+            <artifactId>commons-io</artifactId>
+            <version>2.4</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
             <groupId>org.mockito</groupId>
             <artifactId>mockito-all</artifactId>
             <version>1.8.2</version>
diff --git 
a/src/main/java/org/apache/sling/reqanalyzer/impl/RequestAnalysisLogger.java 
b/src/main/java/org/apache/sling/reqanalyzer/impl/RequestAnalysisLogger.java
index bcf98c4..db1efa6 100644
--- a/src/main/java/org/apache/sling/reqanalyzer/impl/RequestAnalysisLogger.java
+++ b/src/main/java/org/apache/sling/reqanalyzer/impl/RequestAnalysisLogger.java
@@ -23,6 +23,7 @@ import java.io.File;
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.OutputStreamWriter;
+import java.util.Hashtable;
 import java.util.Iterator;
 
 import javax.servlet.Filter;
@@ -45,7 +46,9 @@ import org.apache.sling.api.SlingHttpServletResponse;
 import org.apache.sling.api.wrappers.SlingHttpServletResponseWrapper;
 import org.apache.sling.engine.EngineConstants;
 import org.apache.sling.settings.SlingSettingsService;
+import org.osgi.framework.BundleContext;
 import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceRegistration;
 
 @Component(metatype = false)
 @Service
@@ -59,18 +62,40 @@ public class RequestAnalysisLogger implements Filter {
 
     private BufferedWriter logFile;
 
-    @SuppressWarnings("unused")
+    private RequestAnalyzerWebConsole requestAnalyzerWebConsole;
+    private ServiceRegistration webConsolePlugin;
+
+    @SuppressWarnings({ "serial" })
     @Activate
-    private void activate() throws IOException {
+    private void activate(final BundleContext ctx) throws IOException {
         final File logFile = new File(settings.getSlingHomePath(), 
"logs/requesttracker.txt");
         logFile.getParentFile().mkdirs();
         final FileOutputStream out = new FileOutputStream(logFile, true);
         this.logFile = new BufferedWriter(new OutputStreamWriter(out, 
"UTF-8"));
+
+        this.requestAnalyzerWebConsole = new 
RequestAnalyzerWebConsole(logFile);
+        this.webConsolePlugin = ctx.registerService("javax.servlet.Servlet", 
this.requestAnalyzerWebConsole,
+                new Hashtable<String, Object>() {
+                    {
+                        put("felix.webconsole.label", "requestanalyzer");
+                        put("felix.webconsole.title", "Request Analyzer");
+                        put("felix.webconsole.category", "Sling");
+                    }
+                });
     }
 
-    @SuppressWarnings("unused")
     @Deactivate
     private void deactivate() throws IOException {
+        if (this.webConsolePlugin != null) {
+            this.webConsolePlugin.unregister();
+            this.webConsolePlugin = null;
+        }
+
+        if (this.requestAnalyzerWebConsole != null) {
+            this.requestAnalyzerWebConsole.dispose();
+            this.requestAnalyzerWebConsole = null;
+        }
+
         if (this.logFile != null) {
             this.logFile.close();
             this.logFile = null;
diff --git 
a/src/main/java/org/apache/sling/reqanalyzer/impl/RequestAnalyzerWebConsole.java
 
b/src/main/java/org/apache/sling/reqanalyzer/impl/RequestAnalyzerWebConsole.java
new file mode 100644
index 0000000..4c473e1
--- /dev/null
+++ 
b/src/main/java/org/apache/sling/reqanalyzer/impl/RequestAnalyzerWebConsole.java
@@ -0,0 +1,250 @@
+/*
+ * 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.util.Date;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.zip.Deflater;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipOutputStream;
+
+import javax.servlet.ServletException;
+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 final Set<MainFrame> frames;
+
+    RequestAnalyzerWebConsole(final File logFile) {
+        this.logFile = logFile;
+        this.frames = new HashSet<MainFrame>();
+    }
+
+    void dispose() {
+        final Set<MainFrame> frames = new HashSet<MainFrame>(this.frames);
+        this.frames.clear();
+        for (MainFrame mainFrame : frames) {
+            AWTEvent e = new WindowEvent(mainFrame, 
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) && 
!GraphicsEnvironment.isHeadless()) {
+
+            String target = req.getRequestURI();
+            target = target.substring(0, target.length() - 
WINDOW_MARKER.length());
+
+            showWindow();
+            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 (!GraphicsEnvironment.isHeadless()) {
+            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 void showWindow() throws ServletException, IOException {
+        final File toAnalyze = this.getLogFileCopy();
+
+        final Dimension screenSize = 
Toolkit.getDefaultToolkit().getScreenSize();
+        MainFrame frame = new MainFrame(toAnalyze, Integer.MAX_VALUE, 
screenSize);
+        frame.setVisible(true);
+        frame.toFront();
+
+        // exit the application if the main frame is closed
+        frame.addWindowListener(new WindowAdapter() {
+            @Override
+            public void windowClosing(WindowEvent e) {
+                if (toAnalyze.exists()) {
+                    toAnalyze.delete();
+                }
+            }
+        });
+
+        this.frames.add(frame);
+    }
+
+    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;
+    }
+
+}
diff --git a/src/main/java/org/apache/sling/reqanalyzer/impl/gui/Main.java 
b/src/main/java/org/apache/sling/reqanalyzer/impl/gui/Main.java
index c0efcca..0459b04 100644
--- a/src/main/java/org/apache/sling/reqanalyzer/impl/gui/Main.java
+++ b/src/main/java/org/apache/sling/reqanalyzer/impl/gui/Main.java
@@ -21,6 +21,8 @@ package org.apache.sling.reqanalyzer.impl.gui;
 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.IOException;
 
@@ -54,6 +56,14 @@ public class Main {
 
         MainFrame frame = new MainFrame(file, limit, screenSize);
         frame.setVisible(true);
+
+        // exit the application if the main frame is closed
+        frame.addWindowListener(new WindowAdapter() {
+            @Override
+            public void windowClosing(WindowEvent e) {
+                System.exit(0);
+            }
+        });
     }
 
 }
diff --git a/src/main/java/org/apache/sling/reqanalyzer/impl/gui/MainFrame.java 
b/src/main/java/org/apache/sling/reqanalyzer/impl/gui/MainFrame.java
index 7feb4f1..eccf98c 100644
--- a/src/main/java/org/apache/sling/reqanalyzer/impl/gui/MainFrame.java
+++ b/src/main/java/org/apache/sling/reqanalyzer/impl/gui/MainFrame.java
@@ -20,8 +20,6 @@ package org.apache.sling.reqanalyzer.impl.gui;
 
 import java.awt.Color;
 import java.awt.Dimension;
-import java.awt.event.WindowAdapter;
-import java.awt.event.WindowEvent;
 import java.io.File;
 import java.io.FileNotFoundException;
 import java.io.IOException;
@@ -49,7 +47,7 @@ public class MainFrame extends JFrame {
         JTextPane text = Util.showStartupDialog("Reading from " + file, 
screenSize);
 
         final RequestTrackerFile dm = new RequestTrackerFile(file, limit, 
text);
-        
+
         final JTable table = new JTable(dm);
         table.setAutoCreateRowSorter(true);
         table.setGridColor(Color.GRAY);
@@ -65,14 +63,6 @@ public class MainFrame extends JFrame {
 
         setTitle(file.getPath());
 
-        // exit the application if the main frame is closed
-        addWindowListener(new WindowAdapter() {
-            @Override
-            public void windowClosing(WindowEvent e) {
-                System.exit(0);
-            }
-        });
-
         // setup location and size and ensure updating preferences
         Util.setupComponentLocationSize(this, MAIN_X, MAIN_Y, MAIN_WIDTH, 
MAIN_HEIGHT, (int) screenSize.getWidth() / 4,
                 0, (int) screenSize.getWidth() / 2, (int) 
screenSize.getHeight() / 4);

-- 
To stop receiving notification emails like this one, please contact
"[email protected]" <[email protected]>.

Reply via email to