sling-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From romb...@apache.org
Subject [sling-org-apache-sling-commons-fsclassloader] 13/20: SLING-5601 - The File System Classloader Console Plugin should allow wiping the classloader's cache
Date Tue, 07 Nov 2017 09:21:34 GMT
This is an automated email from the ASF dual-hosted git repository.

rombert pushed a commit to annotated tag org.apache.sling.commons.fsclassloader-1.0.4
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-commons-fsclassloader.git

commit 37162e1adf8bfd9256ea0cd4f36ccba8c9d49292
Author: Radu Cotescu <radu@apache.org>
AuthorDate: Fri Jun 17 16:16:54 2016 +0000

    SLING-5601 - The File System Classloader Console Plugin should allow wiping the classloader's
cache
    
    * added support for clearing the classloader through the web console plug-in
    
    git-svn-id: https://svn.apache.org/repos/asf/sling/trunk/bundles/commons/fsclassloader@1748876
13f79535-47bb-0310-9956-ffa450edef68
---
 pom.xml                                            | 36 ++++++--
 .../impl/FSClassLoaderWebConsole.java              | 59 +++++++++++--
 src/main/resources/res/ui/fsclassloader.js         | 69 +++++++++++++++
 .../impl/FSClassLoaderWebConsoleTest.java          | 98 ++++++++++++++++++++++
 4 files changed, 250 insertions(+), 12 deletions(-)

diff --git a/pom.xml b/pom.xml
index 9a66f0c..dc456de 100644
--- a/pom.xml
+++ b/pom.xml
@@ -120,11 +120,35 @@
             <version>2.5</version>
             <scope>provided</scope>
         </dependency>
-		<dependency>
-			<groupId>org.apache.felix</groupId>
-			<artifactId>org.apache.felix.webconsole</artifactId>
-			<version>3.0.0</version>
-			<scope>provided</scope>
-		</dependency>
+        <dependency>
+            <groupId>org.apache.felix</groupId>
+            <artifactId>org.apache.felix.webconsole</artifactId>
+            <version>3.0.0</version>
+            <scope>provided</scope>
+        </dependency>
+
+        <!-- Testing -->
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.mockito</groupId>
+            <artifactId>mockito-core</artifactId>
+            <version>1.10.19</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.powermock</groupId>
+            <artifactId>powermock-api-mockito</artifactId>
+            <version>1.6.5</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-simple</artifactId>
+            <scope>test</scope>
+        </dependency>
     </dependencies>
 </project>
diff --git a/src/main/java/org/apache/sling/commons/fsclassloader/impl/FSClassLoaderWebConsole.java
b/src/main/java/org/apache/sling/commons/fsclassloader/impl/FSClassLoaderWebConsole.java
index 359fe71..ee5f6a0 100644
--- a/src/main/java/org/apache/sling/commons/fsclassloader/impl/FSClassLoaderWebConsole.java
+++ b/src/main/java/org/apache/sling/commons/fsclassloader/impl/FSClassLoaderWebConsole.java
@@ -39,9 +39,13 @@ import org.apache.felix.scr.annotations.Activate;
 import org.apache.felix.scr.annotations.Component;
 import org.apache.felix.scr.annotations.Properties;
 import org.apache.felix.scr.annotations.Property;
+import org.apache.felix.scr.annotations.Reference;
 import org.apache.felix.scr.annotations.Service;
 import org.apache.felix.webconsole.AbstractWebConsolePlugin;
+import org.apache.sling.commons.classloader.ClassLoaderWriter;
 import org.osgi.service.component.ComponentContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 /**
  * Web Console for the FileSystem Class Loader. Allows users to download Java
@@ -62,6 +66,12 @@ public class FSClassLoaderWebConsole extends AbstractWebConsolePlugin {
     static final String APP_ROOT = "fsclassloader";
 
     static final String RES_LOC = APP_ROOT + "/res/ui";
+    static final String POST_PARAM_CLEAR_CLASSLOADER = "clear";
+
+    private static final Logger LOG = LoggerFactory.getLogger(FSClassLoaderWebConsole.class);
+
+    @Reference(target = "(service.pid=org.apache.sling.commons.fsclassloader.impl.FSClassLoaderProvider)")
+    private ClassLoaderWriter classLoaderWriter;
 
     /**
      * Represents a set of class, java and deps files for a script.
@@ -205,11 +215,42 @@ public class FSClassLoaderWebConsole extends AbstractWebConsolePlugin
{
             IOUtils.copy(
                     getClass().getClassLoader().getResourceAsStream(
                             "/res/ui/prettify.js"), response.getOutputStream());
-        } else {
+        } else if (request.getRequestURI().endsWith(RES_LOC + "/fsclassloader.js")) {
+            response.setContentType("application/javascript");
+            IOUtils.copy(
+                    getClass().getClassLoader().getResourceAsStream(
+                            "/res/ui/fsclassloader.js"), response.getOutputStream());
+        }
+        else {
             super.doGet(request, response);
         }
     }
 
+    @Override
+    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException,
IOException {
+        String clear = req.getParameter(POST_PARAM_CLEAR_CLASSLOADER);
+        boolean shouldClear = Boolean.parseBoolean(clear);
+        if (shouldClear) {
+            if (classLoaderWriter != null) {
+                boolean result = classLoaderWriter.delete("");
+                if (result) {
+                    resp.getWriter().write("{ \"status\" : \"success\" }");
+                    resp.setStatus(HttpServletResponse.SC_OK);
+                } else {
+                    resp.getWriter().write("{ \"status\" : \"failure\", \"message\" : \"unable
to clear classloader; check server log\" }");
+                    resp.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
+                }
+            } else {
+                LOG.error("Cannot get a reference to org.apache.sling.commons.fsclassloader.impl.FSClassLoaderProvider");
+                resp.getWriter().write("{ \"status\" : \"failure\", \"message\" : \"unable
to clear classloader; check server log\" }");
+                resp.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
+            }
+        } else {
+            resp.getWriter().write("{ \"status\" : \"failure\", \"message\" : \"invalid command\"
}");
+            resp.setStatus(HttpServletResponse.SC_BAD_REQUEST);
+        }
+    }
+
     /*
      * (non-Javadoc)
      *
@@ -328,10 +369,13 @@ public class FSClassLoaderWebConsole extends AbstractWebConsolePlugin
{
                 + "/prettify.css\"></link>");
         w.write("<script type=\"text/javascript\" src=\"" + RES_LOC
                 + "/prettify.js\"></script>");
+        w.write("<script type=\"text/javascript\" src=\"" + RES_LOC
+                + "/fsclassloader.js\"></script>");
         w.write("<script>$(document).ready(prettyPrint);</script>");
         w.write("<style>.prettyprint ol.linenums > li { list-style-type: decimal;
} pre.prettyprint { white-space: pre-wrap; }</style>");
         String file = request.getParameter("view");
         File toView = new File(root + file);
+        w.write("<div id=\"classes\">");
         if (!StringUtils.isEmpty(file)) {
             if (isValid(toView)) {
 
@@ -363,7 +407,7 @@ public class FSClassLoaderWebConsole extends AbstractWebConsolePlugin
{
                 InputStream is = null;
                 try {
                     is = new FileInputStream(toView);
-                    String contents = IOUtils.toString(is);
+                    String contents = IOUtils.toString(is, "UTF-8");
                     w.write("<pre class=\"prettyprint linenums\">");
                     w.write(StringEscapeUtils.escapeHtml4(contents));
                     w.write("</pre>");
@@ -374,11 +418,13 @@ public class FSClassLoaderWebConsole extends AbstractWebConsolePlugin
{
                 response.sendError(404, "File " + file + " not found");
             }
         } else {
-
             w.write("<p class=\"statline ui-state-highlight\">File System ClassLoader
Root: "
-                    + root + "</p>");
-
-            w.write("<table class=\"nicetable ui-widget\">");
+                    + root + " <span style=\"float: right\"><button type='button'
id='clear'>Clear Class Loader</button></span></p>");
+            if (scripts.values().size() > 0 ) {
+                w.write("<table class=\"nicetable ui-widget fsclassloader-has-classes\">");
+            } else {
+                w.write("<table class=\"nicetable ui-widget\">");
+            }
             w.write("<tr class=\"header ui-widget-header\">");
             w.write("<th>View</th>");
             w.write("<th>Script</th>");
@@ -395,5 +441,6 @@ public class FSClassLoaderWebConsole extends AbstractWebConsolePlugin
{
             }
             w.write("</table>");
         }
+        w.write("</div>");
     }
 }
diff --git a/src/main/resources/res/ui/fsclassloader.js b/src/main/resources/res/ui/fsclassloader.js
new file mode 100644
index 0000000..4eca6e3
--- /dev/null
+++ b/src/main/resources/res/ui/fsclassloader.js
@@ -0,0 +1,69 @@
+/*******************************************************************************
+ * 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.
+ ******************************************************************************/
+(function () {
+    'use strict';
+
+    $(document).ready(function () {
+        toggleButton(hasClasses());
+
+        $('#clear').on('click', function (e) {
+            e.preventDefault();
+            var classes = hasClasses();
+            if (classes) {
+                clearCache();
+                toggleButton(classes);
+            }
+
+        });
+    });
+
+    function clearCache() {
+        $.ajax({
+            type: 'POST',
+            data: {'clear': true},
+            dataType: 'json',
+            global: false
+        }).success(
+            function () {
+                window.location.reload();
+            }
+        ).fail(
+            function (jqXHR) {
+                var response, message;
+                try {
+                    response = JSON.parse(jqXHR.responseText);
+                    message = response.message;
+                } catch (err) {
+                    // do nothing
+                }
+                if (message) {
+                    alert('Error: ' + message);
+                } else {
+                    alert('An unknown error was encountered. Please check the server logs.');
+                }
+            }
+        );
+    }
+
+    function hasClasses () {
+        return $('table.fsclassloader-has-classes').length > 0;
+    }
+
+    function toggleButton(toggle) {
+        $('#clear').attr('disabled', !toggle);
+    }
+})();
diff --git a/src/test/java/org/apache/sling/commons/fsclassloader/impl/FSClassLoaderWebConsoleTest.java
b/src/test/java/org/apache/sling/commons/fsclassloader/impl/FSClassLoaderWebConsoleTest.java
new file mode 100644
index 0000000..1f7511c
--- /dev/null
+++ b/src/test/java/org/apache/sling/commons/fsclassloader/impl/FSClassLoaderWebConsoleTest.java
@@ -0,0 +1,98 @@
+/*******************************************************************************
+ * 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.commons.fsclassloader.impl;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.sling.commons.classloader.ClassLoaderWriter;
+import org.junit.After;
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.powermock.reflect.Whitebox;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.*;
+
+public class FSClassLoaderWebConsoleTest {
+
+    private FSClassLoaderWebConsole console;
+    private ClassLoaderWriter classLoaderWriter;
+
+    @After
+    public void after() {
+        console = null;
+        classLoaderWriter = null;
+    }
+
+    @Test
+    public void testClearClassLoaderOK() throws Exception {
+        setFixture(true);
+        HttpServletRequest request = mock(HttpServletRequest.class);
+        HttpServletResponse response = mock(HttpServletResponse.class);
+        StringWriter stringWriter = new StringWriter();
+        PrintWriter writer = new PrintWriter(stringWriter);
+        when(response.getWriter()).thenReturn(writer);
+        when(request.getParameter(FSClassLoaderWebConsole.POST_PARAM_CLEAR_CLASSLOADER)).thenReturn("true");
+        console.doPost(request, response);
+        verify(classLoaderWriter).delete("");
+        verify(response).setStatus(HttpServletResponse.SC_OK);
+        assertEquals("{ \"status\" : \"success\" }", stringWriter.toString());
+    }
+
+    @Test
+    public void testClearClassLoaderWrongCommand() throws Exception {
+        setFixture(true);
+        HttpServletRequest request = mock(HttpServletRequest.class);
+        HttpServletResponse response = mock(HttpServletResponse.class);
+        StringWriter stringWriter = new StringWriter();
+        PrintWriter writer = new PrintWriter(stringWriter);
+        when(response.getWriter()).thenReturn(writer);
+        when(request.getParameter(FSClassLoaderWebConsole.POST_PARAM_CLEAR_CLASSLOADER)).thenReturn("random");
+        console.doPost(request, response);
+        verify(classLoaderWriter, Mockito.times(0)).delete("");
+        verify(response).setStatus(HttpServletResponse.SC_BAD_REQUEST);
+        assertEquals("{ \"status\" : \"failure\", \"message\" : \"invalid command\" }", stringWriter.toString());
+    }
+
+    @Test
+    public void testClearClassLoaderUnableToClean() throws Exception {
+        setFixture(false);
+        HttpServletRequest request = mock(HttpServletRequest.class);
+        HttpServletResponse response = mock(HttpServletResponse.class);
+        StringWriter stringWriter = new StringWriter();
+        PrintWriter writer = new PrintWriter(stringWriter);
+        when(response.getWriter()).thenReturn(writer);
+        when(request.getParameter(FSClassLoaderWebConsole.POST_PARAM_CLEAR_CLASSLOADER)).thenReturn("true");
+        console.doPost(request, response);
+        verify(classLoaderWriter).delete("");
+        verify(response).setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
+        assertEquals("{ \"status\" : \"failure\", \"message\" : \"unable to clear classloader;
check server log\" }",
+                stringWriter.toString());
+    }
+
+    private void setFixture(boolean clwReturn) {
+        console = spy(new FSClassLoaderWebConsole());
+        classLoaderWriter = mock(ClassLoaderWriter.class);
+        when(classLoaderWriter.delete("")).thenReturn(clwReturn);
+        Whitebox.setInternalState(console, "classLoaderWriter", classLoaderWriter);
+    }
+
+
+}

-- 
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <commits@sling.apache.org>.

Mime
View raw message