SLING-12924 Migrate common log webconsole plugin to jakarta servlet (#11)
diff --git a/pom.xml b/pom.xml
index 41ab824..6590ffa 100644
--- a/pom.xml
+++ b/pom.xml
@@ -28,7 +28,7 @@
</parent>
<artifactId>org.apache.sling.commons.log.webconsole</artifactId>
- <version>1.0.3-SNAPSHOT</version>
+ <version>2.0.0-SNAPSHOT</version>
<name>Apache Sling Commons Log WebConsole</name>
<description>This bundle provides webconsole plugin for Sling Commons Log</description>
@@ -42,7 +42,7 @@
<properties>
<sling.java.version>17</sling.java.version>
- <slf4j.version>1.7.21</slf4j.version>
+ <slf4j.version>2.0.17</slf4j.version>
<pax-exam.version>4.14.0</pax-exam.version>
<project.build.outputTimestamp>1734083968</project.build.outputTimestamp>
@@ -76,6 +76,7 @@
<dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.framework</artifactId>
+ <version>1.10.0</version>
<scope>provided</scope>
</dependency>
<dependency>
@@ -97,8 +98,9 @@
<!-- servlet API for the web console plugin -->
<dependency>
- <groupId>javax.servlet</groupId>
- <artifactId>javax.servlet-api</artifactId>
+ <groupId>jakarta.servlet</groupId>
+ <artifactId>jakarta.servlet-api</artifactId>
+ <version>6.0.0</version>
<scope>provided</scope>
</dependency>
@@ -120,7 +122,7 @@
<dependency>
<groupId>org.apache.felix</groupId>
<artifactId>org.apache.felix.framework</artifactId>
- <version>7.0.1</version>
+ <version>7.0.5</version>
<scope>test</scope>
</dependency>
diff --git a/src/main/java/org/apache/sling/commons/log/webconsole/internal/Activator.java b/src/main/java/org/apache/sling/commons/log/webconsole/internal/Activator.java
index 15d9b41..e9249b9 100644
--- a/src/main/java/org/apache/sling/commons/log/webconsole/internal/Activator.java
+++ b/src/main/java/org/apache/sling/commons/log/webconsole/internal/Activator.java
@@ -18,32 +18,33 @@
*/
package org.apache.sling.commons.log.webconsole.internal;
+import jakarta.servlet.Servlet;
import org.apache.sling.commons.log.logback.webconsole.LogPanel;
import org.osgi.annotation.bundle.Header;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
import org.osgi.framework.ServiceReference;
+import org.osgi.framework.ServiceRegistration;
import org.osgi.util.tracker.ServiceTracker;
@Header(name = Constants.BUNDLE_ACTIVATOR, value = "${@class}")
public class Activator implements BundleActivator {
- private ServiceTracker<LogPanel, LogWebConsolePlugin> panelTracker;
+ private ServiceTracker<LogPanel, ServiceRegistration<Servlet>> panelTracker;
@Override
public void start(BundleContext context) throws Exception {
- panelTracker = new ServiceTracker<LogPanel, LogWebConsolePlugin>(context, LogPanel.class, null) {
+ panelTracker = new ServiceTracker<LogPanel, ServiceRegistration<Servlet>>(context, LogPanel.class, null) {
@Override
- public LogWebConsolePlugin addingService(ServiceReference<LogPanel> reference) {
+ public ServiceRegistration<Servlet> addingService(ServiceReference<LogPanel> reference) {
LogPanel panel = context.getService(reference);
LogWebConsolePlugin plugin = new LogWebConsolePlugin(panel);
- plugin.register(context);
- return plugin;
+ return plugin.register(context);
}
@Override
- public void removedService(ServiceReference<LogPanel> reference, LogWebConsolePlugin plugin) {
- plugin.unregister();
+ public void removedService(ServiceReference<LogPanel> reference, ServiceRegistration<Servlet> serviceReg) {
+ serviceReg.unregister();
context.ungetService(reference);
}
};
diff --git a/src/main/java/org/apache/sling/commons/log/webconsole/internal/LogWebConsolePlugin.java b/src/main/java/org/apache/sling/commons/log/webconsole/internal/LogWebConsolePlugin.java
index 1a88abd..910eba7 100644
--- a/src/main/java/org/apache/sling/commons/log/webconsole/internal/LogWebConsolePlugin.java
+++ b/src/main/java/org/apache/sling/commons/log/webconsole/internal/LogWebConsolePlugin.java
@@ -18,17 +18,23 @@
*/
package org.apache.sling.commons.log.webconsole.internal;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
import java.io.IOException;
import java.io.PrintWriter;
+import java.util.Dictionary;
+import java.util.Map;
-import org.apache.felix.webconsole.SimpleWebConsolePlugin;
+import jakarta.servlet.Servlet;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import org.apache.felix.webconsole.servlet.AbstractServlet;
+import org.apache.felix.webconsole.servlet.ServletConstants;
import org.apache.sling.commons.log.logback.webconsole.LogPanel;
import org.apache.sling.commons.log.logback.webconsole.LoggerConfig;
import org.apache.sling.commons.log.logback.webconsole.TailerOptions;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.FrameworkUtil;
+import org.osgi.framework.ServiceRegistration;
import static org.apache.sling.commons.log.logback.webconsole.LogPanel.APP_ROOT;
import static org.apache.sling.commons.log.logback.webconsole.LogPanel.PARAM_APPENDER_NAME;
@@ -36,53 +42,78 @@
import static org.apache.sling.commons.log.logback.webconsole.LogPanel.PARAM_TAIL_NUM_OF_LINES;
import static org.apache.sling.commons.log.logback.webconsole.LogPanel.PATH_TAILER;
-public class LogWebConsolePlugin extends SimpleWebConsolePlugin {
+public class LogWebConsolePlugin extends AbstractServlet {
+ private static final long serialVersionUID = 1L;
+
private static final String RES_LOC = LogPanel.APP_ROOT + "/res/ui";
private static final String[] CSS_REFS = {
RES_LOC + "/jquery.autocomplete.css", RES_LOC + "/prettify.css", RES_LOC + "/log.css",
};
- private final LogPanel panel;
+ private final transient LogPanel panel;
public LogWebConsolePlugin(LogPanel panel) {
- super(LogPanel.APP_ROOT, "Log Support", "Sling", CSS_REFS);
this.panel = panel;
}
+ public ServiceRegistration<Servlet> register(BundleContext context) {
+ Dictionary<String, Object> props = FrameworkUtil.asDictionary(Map.of(
+ ServletConstants.PLUGIN_LABEL,
+ LogPanel.APP_ROOT,
+ ServletConstants.PLUGIN_TITLE,
+ "Log Support",
+ ServletConstants.PLUGIN_CATEGORY,
+ "Sling",
+ ServletConstants.PLUGIN_CSS_REFERENCES,
+ CSS_REFS));
+ return context.registerService(Servlet.class, this, props);
+ }
+
+ /**
+ * Override so we can ensure the rendering of the tailer text output
+ * does not contain the html header and footer tags.
+ */
@Override
- protected void renderContent(HttpServletRequest req, HttpServletResponse resp)
- throws ServletException, IOException {
- final PrintWriter pw = resp.getWriter();
- final String consoleAppRoot = getAppRoot(req);
-
- if (req.getPathInfo() != null) {
- if (req.getPathInfo().endsWith(PATH_TAILER)) {
- String appenderName = req.getParameter(PARAM_APPENDER_NAME);
- String regex = req.getParameter(PARAM_TAIL_GREP);
- addNoSniffHeader(resp);
- if (appenderName == null) {
- pw.printf("Provide appender name via [%s] request parameter%n", PARAM_APPENDER_NAME);
- return;
- }
- int numOfLines = 0;
- try {
- numOfLines = Integer.valueOf(req.getParameter(PARAM_TAIL_NUM_OF_LINES));
- } catch (NumberFormatException e) {
- // ignore
- }
- TailerOptions opts = new TailerOptions(numOfLines, regex);
- panel.tail(pw, appenderName, opts);
- return;
- }
+ protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
+ if ("GET".equalsIgnoreCase(req.getMethod())
+ && req.getPathInfo() != null
+ && req.getPathInfo().endsWith(PATH_TAILER)) {
+ renderContent(req, resp);
+ } else {
+ super.service(req, resp);
}
-
- panel.render(pw, consoleAppRoot);
}
@Override
- protected boolean isHtmlRequest(HttpServletRequest request) {
- return !request.getRequestURI().endsWith(PATH_TAILER);
+ public void renderContent(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
+ final PrintWriter pw = resp.getWriter();
+ final String consoleAppRoot = getAppRoot(req);
+
+ if (req.getPathInfo() != null && req.getPathInfo().endsWith(PATH_TAILER)) {
+ // NOTE: set the content type here to ensure that EnhancedPluginAdapter.CheckHttpServletResponse
+ // that is being processed knows that the output is done and doesn't try rendering the html
+ // header and footer tags
+ resp.setContentType("text/plain");
+ String appenderName = req.getParameter(PARAM_APPENDER_NAME);
+ String regex = req.getParameter(PARAM_TAIL_GREP);
+ addNoSniffHeader(resp);
+ if (appenderName == null) {
+ pw.printf("Provide appender name via [%s] request parameter%n", PARAM_APPENDER_NAME);
+ return;
+ }
+ int numOfLines = 0;
+ try {
+ numOfLines = Integer.valueOf(req.getParameter(PARAM_TAIL_NUM_OF_LINES));
+ } catch (NumberFormatException e) {
+ // ignore
+ }
+ TailerOptions opts = new TailerOptions(numOfLines, regex);
+ panel.tail(pw, appenderName, opts);
+ return;
+ }
+
+ panel.render(pw, consoleAppRoot);
}
@Override
diff --git a/src/test/java/org/apache/sling/commons/log/webconsole/ITLogWebConsolePlugin.java b/src/test/java/org/apache/sling/commons/log/webconsole/ITLogWebConsolePlugin.java
index 290766f..294b06a 100644
--- a/src/test/java/org/apache/sling/commons/log/webconsole/ITLogWebConsolePlugin.java
+++ b/src/test/java/org/apache/sling/commons/log/webconsole/ITLogWebConsolePlugin.java
@@ -19,8 +19,8 @@
package org.apache.sling.commons.log.webconsole;
import javax.inject.Inject;
-import javax.servlet.Servlet;
+import jakarta.servlet.Servlet;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.ops4j.pax.exam.junit.PaxExam;
diff --git a/src/test/java/org/apache/sling/commons/log/webconsole/ITWebConsoleRemote.java b/src/test/java/org/apache/sling/commons/log/webconsole/ITWebConsoleRemote.java
index 73fe1a0..4ac3410 100644
--- a/src/test/java/org/apache/sling/commons/log/webconsole/ITWebConsoleRemote.java
+++ b/src/test/java/org/apache/sling/commons/log/webconsole/ITWebConsoleRemote.java
@@ -22,6 +22,7 @@
import java.io.IOException;
import org.apache.commons.io.FilenameUtils;
+import org.apache.sling.commons.log.logback.webconsole.LogPanel;
import org.apache.sling.commons.log.webconsole.remote.WebConsoleTestActivator;
import org.htmlunit.DefaultCredentialsProvider;
import org.htmlunit.Page;
@@ -152,6 +153,17 @@
assertThat(text, not(containsString(WebConsoleTestActivator.BAR_LOG)));
}
+ @Test
+ public void tailerGrepWithoutAppenderName() throws Exception {
+ TextPage page = webClient.getPage(prepareUrl("slinglog/tailer.txt"));
+ String text = page.getContent();
+
+ assertThat(
+ text,
+ containsString(String.format(
+ "Provide appender name via [%s] request parameter", LogPanel.PARAM_APPENDER_NAME)));
+ }
+
@AfterClass
public static void tearDownClass() {
if (testContainer != null) {
diff --git a/src/test/java/org/apache/sling/commons/log/webconsole/LogTestBase.java b/src/test/java/org/apache/sling/commons/log/webconsole/LogTestBase.java
index a3ef60e..2ddd1c2 100644
--- a/src/test/java/org/apache/sling/commons/log/webconsole/LogTestBase.java
+++ b/src/test/java/org/apache/sling/commons/log/webconsole/LogTestBase.java
@@ -55,7 +55,7 @@
// the name of the system property which captures the jococo coverage agent
// command
// if specified then agent would be specified otherwise ignored
- protected static final String COVERAGE_COMMAND = "coverage.command";
+ protected static final String COVERAGE_COMMAND = "jacoco.it.command";
// the default bundle jar file name
protected static final String BUNDLE_JAR_DEFAULT = "target/slinglogback-webconsole.jar";
diff --git a/src/test/java/org/apache/sling/commons/log/webconsole/remote/WebConsoleTestActivator.java b/src/test/java/org/apache/sling/commons/log/webconsole/remote/WebConsoleTestActivator.java
index c4bc407..75f4403 100644
--- a/src/test/java/org/apache/sling/commons/log/webconsole/remote/WebConsoleTestActivator.java
+++ b/src/test/java/org/apache/sling/commons/log/webconsole/remote/WebConsoleTestActivator.java
@@ -50,7 +50,7 @@
public static final String FOO_LOG = "WebConsoleTestActivator-Foo";
public static final String BAR_LOG = "WebConsoleTestActivator-BAR";
- public static Class[] BUNDLE_CLASS_NAMES = {
+ public static Class<?>[] BUNDLE_CLASS_NAMES = {
WebConsoleTestActivator.class,
WebConsoleTestTurboFilter.class,
WebConsoleTestConfigProvider.class,