You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by ro...@apache.org on 2017/10/20 14:35:08 UTC
[sling-org-apache-sling-commons-fsclassloader] 17/33: SLING-5601 -
The File System Classloader Console Plugin should allow wiping the
classloader's cache
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-commons-fsclassloader.git
commit d4065c9d541424fcb3ec2ca9b8831e93a45fb300
Author: Radu Cotescu <ra...@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@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" <co...@sling.apache.org>.