diff --git a/activemq-web-console/pom.xml b/activemq-web-console/pom.xml index 654f9af2f54..37efbf858e8 100644 --- a/activemq-web-console/pom.xml +++ b/activemq-web-console/pom.xml @@ -216,6 +216,7 @@ ${project.groupId} activemq-stomp + ${project.groupId} activemq-spring @@ -241,10 +242,10 @@ org.springframework spring-web - + org.springframework - spring-webmvc + spring-context diff --git a/activemq-web-console/src/main/java/org/apache/activemq/web/ActionServlet.java b/activemq-web-console/src/main/java/org/apache/activemq/web/ActionServlet.java new file mode 100644 index 00000000000..8cd3b7c50a5 --- /dev/null +++ b/activemq-web-console/src/main/java/org/apache/activemq/web/ActionServlet.java @@ -0,0 +1,124 @@ +/** + * 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.activemq.web; + +import java.io.IOException; +import java.util.Arrays; +import java.util.Map; +import java.util.Optional; + +import static java.util.Map.entry; + +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServlet; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; + +import org.apache.activemq.web.controller.*; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.web.bind.ServletRequestDataBinder; +import org.springframework.web.context.WebApplicationContext; +import org.springframework.web.context.support.WebApplicationContextUtils; + +/** + * Servlet that routes requests to the appropriate controller class and injects the request parameters into it. + */ +public class ActionServlet extends HttpServlet { + + private static final Logger LOG = LoggerFactory.getLogger(ActionServlet.class); + + private static final Map> routes = Map.ofEntries( + entry("/createDestination.action", CreateDestination.class), + entry("/deleteDestination.action", DeleteDestination.class), + entry("/createSubscriber.action", CreateSubscriber.class), + entry("/deleteSubscriber.action", DeleteSubscriber.class), + entry("/sendMessage.action", SendMessage.class), + entry("/purgeDestination.action", PurgeDestination.class), + entry("/deleteMessage.action", DeleteMessage.class), + entry("/copyMessage.action", CopyMessage.class), + entry("/moveMessage.action", MoveMessage.class), + entry("/deleteJob.action", DeleteJob.class), + entry("/retryMessage.action", RetryMessage.class), + entry("/pauseDestination.action", PauseDestination.class), + entry("/resumeDestination.action", ResumeDestination.class) + ); + + private WebApplicationContext context; + + @Override + public void init() throws ServletException { + super.init(); + context = WebApplicationContextUtils.getWebApplicationContext(getServletContext()); + if (context == null) { + throw new IllegalStateException("Failed to initialize Web Application Context"); + } + LOG.info("Action Servlet initialized"); + } + + @Override + protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + try { + LOG.info("Received request for action with path {}", request.getRequestURI()); + + final String actionPath = getAction(request); + final Optional maybeController = getHandler(actionPath); + if (maybeController.isEmpty()) { + // Path does not route to any request + LOG.warn("No action is mapped to path: {} ({})", request.getRequestURI(), actionPath); + response.sendError(HttpServletResponse.SC_NOT_FOUND); + return; + } + + final Controller controller = maybeController.get(); + + checkMethodIsSupported(controller, request); + injectRequestDataIntoController(controller, request); + + LOG.info("Handling action: {} with {}", actionPath, controller); + + controller.handleRequest(request, response); + } catch (Exception e) { + throw new ServletException(e); + } + } + + private String getAction(final HttpServletRequest request) { + String path = request.getRequestURI(); + if (path.contains("/")) { + path = path.substring(path.lastIndexOf("/")); + } + return path; + } + + private Optional getHandler(final String path) { + return Optional.ofNullable(routes.get(path)).map(context::getBean); + } + + private void checkMethodIsSupported(final Controller controller, final HttpServletRequest request) { + if (controller instanceof DestinationFacade destination) { + if (!Arrays.asList(destination.getSupportedHttpMethods()).contains(request.getMethod())) { + throw new UnsupportedOperationException("Unsupported method " + request.getMethod()); + } + } + } + + private void injectRequestDataIntoController(final Controller controller, final HttpServletRequest request) { + final ServletRequestDataBinder binder = new ServletRequestDataBinder(controller); + binder.bind(request); + } +} \ No newline at end of file diff --git a/activemq-web-console/src/main/java/org/apache/activemq/web/controller/Controller.java b/activemq-web-console/src/main/java/org/apache/activemq/web/controller/Controller.java new file mode 100644 index 00000000000..4018aedbef6 --- /dev/null +++ b/activemq-web-console/src/main/java/org/apache/activemq/web/controller/Controller.java @@ -0,0 +1,27 @@ +/** + * 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.activemq.web.controller; + +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; + +/** + * Controller implementations contain the logic responsible for handling an HTTP Request. + */ +public interface Controller { + void handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception; +} \ No newline at end of file diff --git a/activemq-web-console/src/main/java/org/apache/activemq/web/controller/CopyMessage.java b/activemq-web-console/src/main/java/org/apache/activemq/web/controller/CopyMessage.java index 958e2b3f4de..03f4014a6bf 100644 --- a/activemq-web-console/src/main/java/org/apache/activemq/web/controller/CopyMessage.java +++ b/activemq-web-console/src/main/java/org/apache/activemq/web/controller/CopyMessage.java @@ -24,32 +24,35 @@ import org.apache.activemq.web.DestinationFacade; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.web.servlet.ModelAndView; -import org.springframework.web.servlet.mvc.Controller; +import org.springframework.stereotype.Component; +import org.springframework.web.context.annotation.RequestScope; /** * Copies a message from one to another queue */ +@Component +@RequestScope public class CopyMessage extends DestinationFacade implements Controller { private String messageId; private String destination; private static final Logger log = LoggerFactory.getLogger(CopyMessage.class); - public CopyMessage(BrokerFacade brokerFacade) { + public CopyMessage(final BrokerFacade brokerFacade) { super(brokerFacade); } - public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception { + @Override + public void handleRequest(final HttpServletRequest request, final HttpServletResponse response) throws Exception { if (messageId != null) { QueueViewMBean queueView = getQueueView(); if (queueView != null) { - log.info(getJMSDestination() + "(" + messageId + ")" + " copy to " + destination); + log.info("{} ({}) copy to {}", getJMSDestination(), messageId, destination); queueView.copyMessageTo(messageId, destination); } else { - log.warn("No queue named: " + getPhysicalDestinationName()); + log.warn("No queue named: {}", getPhysicalDestinationName()); } } - return redirectToDestinationView(); + response.sendRedirect("browse.jsp?JMSDestination=" + getJMSDestination()); } public String getMessageId() { @@ -59,8 +62,6 @@ public String getMessageId() { public void setMessageId(String messageId) { this.messageId = messageId; } - - public String getDestination() { return destination; @@ -69,5 +70,4 @@ public String getDestination() { public void setDestination(String destination) { this.destination = destination; } - } diff --git a/activemq-web-console/src/main/java/org/apache/activemq/web/controller/CreateDestination.java b/activemq-web-console/src/main/java/org/apache/activemq/web/controller/CreateDestination.java index b0336653753..93599b0edce 100644 --- a/activemq-web-console/src/main/java/org/apache/activemq/web/controller/CreateDestination.java +++ b/activemq-web-console/src/main/java/org/apache/activemq/web/controller/CreateDestination.java @@ -21,28 +21,23 @@ import org.apache.activemq.web.BrokerFacade; import org.apache.activemq.web.DestinationFacade; -import org.springframework.web.servlet.ModelAndView; -import org.springframework.web.servlet.mvc.Controller; +import org.springframework.stereotype.Component; +import org.springframework.web.context.annotation.RequestScope; -/** - * - * - */ +@Component +@RequestScope public class CreateDestination extends DestinationFacade implements Controller { public CreateDestination(BrokerFacade brokerFacade) { super(brokerFacade); } - public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception { + public void handleRequest(final HttpServletRequest request, final HttpServletResponse response) throws Exception { addDestination(); - return redirectToBrowseView(); + response.sendRedirect(isQueue() ? "queues.jsp" : "topics.jsp"); } public String[] getSupportedHttpMethods() { return new String[]{"POST"}; } - - - } diff --git a/activemq-web-console/src/main/java/org/apache/activemq/web/controller/CreateSubscriber.java b/activemq-web-console/src/main/java/org/apache/activemq/web/controller/CreateSubscriber.java index 80ec856c881..e52471fb69a 100644 --- a/activemq-web-console/src/main/java/org/apache/activemq/web/controller/CreateSubscriber.java +++ b/activemq-web-console/src/main/java/org/apache/activemq/web/controller/CreateSubscriber.java @@ -21,17 +21,15 @@ import org.apache.activemq.web.BrokerFacade; import org.apache.activemq.web.DurableSubscriberFacade; -import org.springframework.web.servlet.ModelAndView; -import org.springframework.web.servlet.mvc.Controller; +import org.springframework.stereotype.Component; +import org.springframework.web.context.annotation.RequestScope; -/** - * - * - */ +@Component +@RequestScope public class CreateSubscriber extends DurableSubscriberFacade implements Controller { private String selector; - public CreateSubscriber(BrokerFacade brokerFacade) { + public CreateSubscriber(final BrokerFacade brokerFacade) { super(brokerFacade); } @@ -46,16 +44,15 @@ public void setSelector(String selector) { this.selector = selector; } - public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception { - if (selector != null && selector.length() == 0) { + public void handleRequest(final HttpServletRequest request, final HttpServletResponse response) throws Exception { + if (selector != null && selector.isEmpty()) { selector = null; } getBrokerAdmin().createDurableSubscriber(getClientId(), getSubscriberName(), getValidDestination(), selector); - return new ModelAndView("redirect:subscribers.jsp"); + response.sendRedirect("subscribers.jsp"); } public String[] getSupportedHttpMethods() { return new String[]{"POST"}; } - } diff --git a/activemq-web-console/src/main/java/org/apache/activemq/web/controller/DeleteDestination.java b/activemq-web-console/src/main/java/org/apache/activemq/web/controller/DeleteDestination.java index 945edfc5a55..8750410e86f 100644 --- a/activemq-web-console/src/main/java/org/apache/activemq/web/controller/DeleteDestination.java +++ b/activemq-web-console/src/main/java/org/apache/activemq/web/controller/DeleteDestination.java @@ -21,23 +21,19 @@ import org.apache.activemq.web.BrokerFacade; import org.apache.activemq.web.DestinationFacade; -import org.springframework.web.servlet.ModelAndView; -import org.springframework.web.servlet.mvc.Controller; +import org.springframework.stereotype.Component; +import org.springframework.web.context.annotation.RequestScope; -/** - * - * - */ +@Component +@RequestScope public class DeleteDestination extends DestinationFacade implements Controller { - public DeleteDestination(BrokerFacade brokerFacade) { + public DeleteDestination(final BrokerFacade brokerFacade) { super(brokerFacade); } - public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception { + public void handleRequest(final HttpServletRequest request, final HttpServletResponse response) throws Exception { removeDestination(); - return redirectToBrowseView(); + response.sendRedirect(isQueue() ? "queues.jsp" : "topics.jsp"); } - - } diff --git a/activemq-web-console/src/main/java/org/apache/activemq/web/controller/DeleteJob.java b/activemq-web-console/src/main/java/org/apache/activemq/web/controller/DeleteJob.java index 04bfbb22f78..48b54eeb7f7 100644 --- a/activemq-web-console/src/main/java/org/apache/activemq/web/controller/DeleteJob.java +++ b/activemq-web-console/src/main/java/org/apache/activemq/web/controller/DeleteJob.java @@ -23,39 +23,37 @@ import org.apache.activemq.web.DestinationFacade; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.web.servlet.ModelAndView; -import org.springframework.web.servlet.mvc.Controller; +import org.springframework.stereotype.Component; +import org.springframework.web.context.annotation.RequestScope; -/** - * - */ +@Component +@RequestScope public class DeleteJob extends DestinationFacade implements Controller { private String jobId; private static final Logger LOG = LoggerFactory.getLogger(DeleteJob.class); - public DeleteJob(BrokerFacade brokerFacade) { + public DeleteJob(final BrokerFacade brokerFacade) { super(brokerFacade); } - public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception { + public void handleRequest(final HttpServletRequest request, final HttpServletResponse response) throws Exception { if (jobId != null) { JobSchedulerViewMBean jobScheduler = getBrokerFacade().getJobScheduler(); if (jobScheduler != null) { jobScheduler.removeJob(jobId); - LOG.info("Removed scheduled Job " + jobId); + LOG.info("Removed scheduled Job {}", jobId); } else { LOG.warn("Scheduler not configured"); } } - return new ModelAndView("redirect:scheduled.jsp"); + response.sendRedirect("scheduled.jsp"); } public String getJobId() { return jobId; } - public void setJobId(String id) { - this.jobId=id; + public void setJobId(final String id) { + this.jobId = id; } - } diff --git a/activemq-web-console/src/main/java/org/apache/activemq/web/controller/DeleteMessage.java b/activemq-web-console/src/main/java/org/apache/activemq/web/controller/DeleteMessage.java index 6ffc249760b..151aea5497c 100644 --- a/activemq-web-console/src/main/java/org/apache/activemq/web/controller/DeleteMessage.java +++ b/activemq-web-console/src/main/java/org/apache/activemq/web/controller/DeleteMessage.java @@ -24,38 +24,37 @@ import org.apache.activemq.web.DestinationFacade; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.web.servlet.ModelAndView; -import org.springframework.web.servlet.mvc.Controller; +import org.springframework.stereotype.Component; +import org.springframework.web.context.annotation.RequestScope; -/** - * - */ +@Component +@RequestScope public class DeleteMessage extends DestinationFacade implements Controller { private String messageId; private static final Logger log = LoggerFactory.getLogger(DeleteMessage.class); - public DeleteMessage(BrokerFacade brokerFacade) { + public DeleteMessage(final BrokerFacade brokerFacade) { super(brokerFacade); } - public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception { + public void handleRequest(final HttpServletRequest request, final HttpServletResponse response) throws Exception { if (messageId != null) { - QueueViewMBean queueView = getQueueView(); + final QueueViewMBean queueView = getQueueView(); if (queueView != null) { - log.info("Removing message " + getJMSDestination() + "(" + messageId + ")"); + log.info("Removing message {} ({})", getJMSDestination(), messageId); queueView.removeMessage(messageId); } else { - log.warn("No queue named: " + getPhysicalDestinationName()); + log.warn("No queue named: {}", getPhysicalDestinationName()); } } - return redirectToDestinationView(); + response.sendRedirect("browse.jsp?JMSDestination=" + getJMSDestination()); } public String getMessageId() { return messageId; } - public void setMessageId(String messageId) { + public void setMessageId(final String messageId) { this.messageId = messageId; } diff --git a/activemq-web-console/src/main/java/org/apache/activemq/web/controller/DeleteSubscriber.java b/activemq-web-console/src/main/java/org/apache/activemq/web/controller/DeleteSubscriber.java index d54b0123418..a71d3ac4360 100644 --- a/activemq-web-console/src/main/java/org/apache/activemq/web/controller/DeleteSubscriber.java +++ b/activemq-web-console/src/main/java/org/apache/activemq/web/controller/DeleteSubscriber.java @@ -21,22 +21,19 @@ import org.apache.activemq.web.BrokerFacade; import org.apache.activemq.web.DurableSubscriberFacade; -import org.springframework.web.servlet.ModelAndView; -import org.springframework.web.servlet.mvc.Controller; +import org.springframework.stereotype.Component; +import org.springframework.web.context.annotation.RequestScope; -/** - * - * - */ +@Component +@RequestScope public class DeleteSubscriber extends DurableSubscriberFacade implements Controller { public DeleteSubscriber(BrokerFacade brokerFacade) { super(brokerFacade); } - public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception { + public void handleRequest(final HttpServletRequest request, final HttpServletResponse response) throws Exception { getBrokerAdmin().destroyDurableSubscriber(getClientId(), getSubscriberName()); - return new ModelAndView("redirect:subscribers.jsp"); + response.sendRedirect("subscribers.jsp"); } - } diff --git a/activemq-web-console/src/main/java/org/apache/activemq/web/controller/MoveMessage.java b/activemq-web-console/src/main/java/org/apache/activemq/web/controller/MoveMessage.java index e5e3487d206..8fef1734e60 100644 --- a/activemq-web-console/src/main/java/org/apache/activemq/web/controller/MoveMessage.java +++ b/activemq-web-console/src/main/java/org/apache/activemq/web/controller/MoveMessage.java @@ -24,12 +24,14 @@ import org.apache.activemq.web.DestinationFacade; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.web.servlet.ModelAndView; -import org.springframework.web.servlet.mvc.Controller; +import org.springframework.stereotype.Component; +import org.springframework.web.context.annotation.RequestScope; /** * Moves a message from one to another queue */ +@Component +@RequestScope public class MoveMessage extends DestinationFacade implements Controller { private String messageId; private String destination; @@ -39,17 +41,17 @@ public MoveMessage(BrokerFacade brokerFacade) { super(brokerFacade); } - public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception { + public void handleRequest(final HttpServletRequest request, final HttpServletResponse response) throws Exception { if (messageId != null) { - QueueViewMBean queueView = getQueueView(); + final QueueViewMBean queueView = getQueueView(); if (queueView != null) { - log.info("Moving message " + getJMSDestination() + "(" + messageId + ")" + " to " + destination); + log.info("Moving message {} ({}) to {}", getJMSDestination(), messageId, destination); queueView.moveMessageTo(messageId, destination); } else { - log.warn("No queue named: " + getPhysicalDestinationName()); + log.warn("No queue named: {}", getPhysicalDestinationName()); } } - return redirectToDestinationView(); + response.sendRedirect("browse.jsp?JMSDestination=" + getJMSDestination()); } public String getMessageId() { @@ -67,5 +69,4 @@ public String getDestination() { public void setDestination(String destination) { this.destination = destination; } - } diff --git a/activemq-web-console/src/main/java/org/apache/activemq/web/controller/PauseDestination.java b/activemq-web-console/src/main/java/org/apache/activemq/web/controller/PauseDestination.java index 0f3876332cf..1a7113983c9 100644 --- a/activemq-web-console/src/main/java/org/apache/activemq/web/controller/PauseDestination.java +++ b/activemq-web-console/src/main/java/org/apache/activemq/web/controller/PauseDestination.java @@ -18,32 +18,30 @@ import org.apache.activemq.web.BrokerFacade; import org.apache.activemq.web.DestinationFacade; -import org.springframework.web.servlet.ModelAndView; -import org.springframework.web.servlet.mvc.Controller; +import org.springframework.stereotype.Component; +import org.springframework.web.context.annotation.RequestScope; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; -/** - * - * - */ +@Component +@RequestScope public class PauseDestination extends DestinationFacade implements Controller { - public PauseDestination(BrokerFacade brokerFacade) { + public PauseDestination(final BrokerFacade brokerFacade) { super(brokerFacade); } - public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception { + public void handleRequest(final HttpServletRequest request, final HttpServletResponse response) throws Exception { pauseDestination(); - return redirectToBrowseView(); + response.sendRedirect(isQueue() ? "queues.jsp" : "topics.jsp"); } public void pauseDestination() throws Exception { if (isQueue()) { getQueueView().pause(); } else { - throw new UnsupportedOperationException("Pause supported for queues only. Receieved JMSDestinationType=" + getJMSDestinationType()); + throw new UnsupportedOperationException("Pause supported for queues only. Received JMSDestinationType=" + getJMSDestinationType()); } } } diff --git a/activemq-web-console/src/main/java/org/apache/activemq/web/controller/PurgeDestination.java b/activemq-web-console/src/main/java/org/apache/activemq/web/controller/PurgeDestination.java index 0b6da64bf87..9af0761869f 100644 --- a/activemq-web-console/src/main/java/org/apache/activemq/web/controller/PurgeDestination.java +++ b/activemq-web-console/src/main/java/org/apache/activemq/web/controller/PurgeDestination.java @@ -21,28 +21,27 @@ import org.apache.activemq.web.BrokerFacade; import org.apache.activemq.web.DestinationFacade; -import org.springframework.web.servlet.ModelAndView; -import org.springframework.web.servlet.mvc.Controller; +import org.springframework.stereotype.Component; +import org.springframework.web.context.annotation.RequestScope; -/** - * - */ +@Component +@RequestScope public class PurgeDestination extends DestinationFacade implements Controller { - public PurgeDestination(BrokerFacade brokerFacade) { + public PurgeDestination(final BrokerFacade brokerFacade) { super(brokerFacade); } - public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception { + public void handleRequest(final HttpServletRequest request, final HttpServletResponse response) throws Exception { purgeDestination(); - return redirectToBrowseView(); + response.sendRedirect(isQueue() ? "queues.jsp" : "topics.jsp"); } public void purgeDestination() throws Exception { if (isQueue()) { getBrokerFacade().purgeQueue(createDestination()); } else { - throw new UnsupportedOperationException("Purge supported for queues only. Receieved JMSDestinationType=" + getJMSDestinationType()); + throw new UnsupportedOperationException("Purge supported for queues only. Received JMSDestinationType=" + getJMSDestinationType()); } } } diff --git a/activemq-web-console/src/main/java/org/apache/activemq/web/controller/ResumeDestination.java b/activemq-web-console/src/main/java/org/apache/activemq/web/controller/ResumeDestination.java index 8eacee72eb4..714499cebe6 100644 --- a/activemq-web-console/src/main/java/org/apache/activemq/web/controller/ResumeDestination.java +++ b/activemq-web-console/src/main/java/org/apache/activemq/web/controller/ResumeDestination.java @@ -18,32 +18,30 @@ import org.apache.activemq.web.BrokerFacade; import org.apache.activemq.web.DestinationFacade; -import org.springframework.web.servlet.ModelAndView; -import org.springframework.web.servlet.mvc.Controller; +import org.springframework.stereotype.Component; +import org.springframework.web.context.annotation.RequestScope; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; -/** - * - * - */ +@Component +@RequestScope public class ResumeDestination extends DestinationFacade implements Controller { - public ResumeDestination(BrokerFacade brokerFacade) { + public ResumeDestination(final BrokerFacade brokerFacade) { super(brokerFacade); } - public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception { + public void handleRequest(final HttpServletRequest request, final HttpServletResponse response) throws Exception { resumeDestination(); - return redirectToBrowseView(); + response.sendRedirect(isQueue() ? "queues.jsp" : "topics.jsp"); } public void resumeDestination() throws Exception { if (isQueue()) { getQueueView().resume(); } else { - throw new UnsupportedOperationException("Resume supported for queues only. Receieved JMSDestinationType=" + getJMSDestinationType()); + throw new UnsupportedOperationException("Resume supported for queues only. Received JMSDestinationType=" + getJMSDestinationType()); } } } diff --git a/activemq-web-console/src/main/java/org/apache/activemq/web/controller/RetryMessage.java b/activemq-web-console/src/main/java/org/apache/activemq/web/controller/RetryMessage.java index 0cbeec1313f..4fd7bc1a25f 100644 --- a/activemq-web-console/src/main/java/org/apache/activemq/web/controller/RetryMessage.java +++ b/activemq-web-console/src/main/java/org/apache/activemq/web/controller/RetryMessage.java @@ -21,8 +21,8 @@ import org.apache.activemq.web.DestinationFacade; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.web.servlet.ModelAndView; -import org.springframework.web.servlet.mvc.Controller; +import org.springframework.stereotype.Component; +import org.springframework.web.context.annotation.RequestScope; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; @@ -30,32 +30,35 @@ /** * Retry a message on a queue. */ +@Component +@RequestScope public class RetryMessage extends DestinationFacade implements Controller { - private String messageId; private static final Logger log = LoggerFactory.getLogger(MoveMessage.class); - public RetryMessage(BrokerFacade brokerFacade) { + private String messageId; + + public RetryMessage(final BrokerFacade brokerFacade) { super(brokerFacade); } - public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception { + public void handleRequest(final HttpServletRequest request, final HttpServletResponse response) throws Exception { if (messageId != null) { QueueViewMBean queueView = getQueueView(); if (queueView != null) { - log.info("Retrying message " + getJMSDestination() + "(" + messageId + ")"); + log.info("Retrying message {} ({})", getJMSDestination(), messageId); queueView.retryMessage(messageId); } else { - log.warn("No queue named: " + getPhysicalDestinationName()); + log.warn("No queue named: {}", getPhysicalDestinationName()); } } - return redirectToDestinationView(); + response.sendRedirect("browse.jsp?JMSDestination=" + getJMSDestination()); } public String getMessageId() { return messageId; } - public void setMessageId(String messageId) { + public void setMessageId(final String messageId) { this.messageId = messageId; } diff --git a/activemq-web-console/src/main/java/org/apache/activemq/web/controller/SendMessage.java b/activemq-web-console/src/main/java/org/apache/activemq/web/controller/SendMessage.java index 2c61097b0eb..7fa3b1968f3 100644 --- a/activemq-web-console/src/main/java/org/apache/activemq/web/controller/SendMessage.java +++ b/activemq-web-console/src/main/java/org/apache/activemq/web/controller/SendMessage.java @@ -26,12 +26,14 @@ import org.apache.activemq.web.BrokerFacade; import org.apache.activemq.web.DestinationFacade; import org.apache.activemq.web.WebClient; -import org.springframework.web.servlet.ModelAndView; -import org.springframework.web.servlet.mvc.Controller; +import org.springframework.stereotype.Component; +import org.springframework.web.context.annotation.RequestScope; /** * Sends a message */ +@Component +@RequestScope public class SendMessage extends DestinationFacade implements Controller { private String jmsText; @@ -43,32 +45,26 @@ public class SendMessage extends DestinationFacade implements Controller { private String jmsType; private int jmsMessageCount = 1; private String jmsMessageCountHeader = "JMSXMessageNumber"; - private boolean redirectToBrowse; - public SendMessage(BrokerFacade brokerFacade) { + public SendMessage(final BrokerFacade brokerFacade) { super(brokerFacade); } - public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception { + public void handleRequest(final HttpServletRequest request, final HttpServletResponse response) throws Exception { WebClient client = WebClient.getWebClient(request); ActiveMQDestination dest = createDestination(); sendMessages(request, client, dest); - if (redirectToBrowse) { - if (isQueue()) { - return new ModelAndView("redirect:browse.jsp?destination=" + getJMSDestination()); - } - } - return redirectToBrowseView(); + response.sendRedirect(isQueue() ? "queues.jsp" : "topics.jsp"); } - protected void sendMessages(HttpServletRequest request, WebClient client, ActiveMQDestination dest) + protected void sendMessages(final HttpServletRequest request, final WebClient client, final ActiveMQDestination dest) throws JMSException { if (jmsMessageCount <= 1) { jmsMessageCount = 1; } for (int i = 0; i < jmsMessageCount; i++) { - Message message = createMessage(client, request); + Message message = createMessage(client); appendHeaders(message, request); if (jmsMessageCount > 1) { message.setIntProperty(jmsMessageCountHeader, i + 1); @@ -118,7 +114,7 @@ public boolean isJMSPersistent() { return jmsPersistent; } - public void setJMSPersistent(boolean persistent) { + public void setJMSPersistent(final boolean persistent) { this.jmsPersistent = persistent; } @@ -126,7 +122,7 @@ public int getJMSPriority() { return jmsPriority; } - public void setJMSPriority(int priority) { + public void setJMSPriority(final int priority) { this.jmsPriority = priority; } @@ -134,7 +130,7 @@ public String getJMSText() { return jmsText; } - public void setJMSText(String text) { + public void setJMSText(final String text) { this.jmsText = text; } @@ -142,7 +138,7 @@ public int getJMSTimeToLive() { return jmsTimeToLive; } - public void setJMSTimeToLive(int timeToLive) { + public void setJMSTimeToLive(final int timeToLive) { this.jmsTimeToLive = timeToLive; } @@ -150,7 +146,7 @@ public int getJMSMessageCount() { return jmsMessageCount; } - public void setJMSMessageCount(int copies) { + public void setJMSMessageCount(final int copies) { jmsMessageCount = copies; } @@ -167,7 +163,7 @@ public void setJMSMessageCountHeader(String messageCountHeader) { // Implementation methods // ------------------------------------------------------------------------- - protected Message createMessage(WebClient client, HttpServletRequest request) throws JMSException { + protected Message createMessage(final WebClient client) throws JMSException { if (jmsText != null) { return client.getSession().createTextMessage(jmsText); } @@ -176,14 +172,14 @@ protected Message createMessage(WebClient client, HttpServletRequest request) th } @SuppressWarnings("rawtypes") - protected void appendHeaders(Message message, HttpServletRequest request) throws JMSException { + protected void appendHeaders(final Message message, final HttpServletRequest request) throws JMSException { message.setJMSCorrelationID(jmsCorrelationID); - if (jmsReplyTo != null && jmsReplyTo.trim().length() > 0) { + if (jmsReplyTo != null && !jmsReplyTo.trim().isEmpty()) { message.setJMSReplyTo(ActiveMQDestination.createDestination(jmsReplyTo, ActiveMQDestination.QUEUE_TYPE)); } message.setJMSType(jmsType); - // now lets add all of the parameters + // now lets add all the parameters Map map = request.getParameterMap(); if (map != null) { for (Iterator iter = map.entrySet().iterator(); iter.hasNext();) { @@ -205,28 +201,28 @@ protected void appendHeaders(Message message, HttpServletRequest request) throws if ((name.equals("AMQ_SCHEDULED_DELAY") || name.equals("AMQ_SCHEDULED_PERIOD"))) { if (value != null) { String str = value.toString().trim(); - if (str.length() > 0) { + if (!str.isEmpty()) { message.setLongProperty(name, Long.parseLong(str)); } } } else if (name.equals("AMQ_SCHEDULED_REPEAT")) { if (value != null) { String str = value.toString().trim(); - if (str.length() > 0) { + if (!str.isEmpty()) { message.setIntProperty(name, Integer.parseInt(str)); } } } else if (name.equals("AMQ_SCHEDULED_CRON")) { if (value != null) { String str = value.toString().trim(); - if (str.length() > 0) { + if (!str.isEmpty()) { message.setStringProperty(name, str); } } } else { if (value instanceof String) { String text = value.toString().trim(); - if (text.length() == 0) { + if (text.isEmpty()) { value = null; } else { value = text; @@ -240,7 +236,7 @@ protected void appendHeaders(Message message, HttpServletRequest request) throws } } } - protected boolean isValidPropertyName(String name) { + protected boolean isValidPropertyName(final String name) { // allow JMSX extensions or non JMS properties return name.startsWith("JMSX") || !name.startsWith("JMS"); } diff --git a/activemq-web-console/src/main/java/org/apache/activemq/web/filter/ApplicationContextFilter.java b/activemq-web-console/src/main/java/org/apache/activemq/web/filter/ApplicationContextFilter.java index a82e9f4a98a..2a1a712cca6 100644 --- a/activemq-web-console/src/main/java/org/apache/activemq/web/filter/ApplicationContextFilter.java +++ b/activemq-web-console/src/main/java/org/apache/activemq/web/filter/ApplicationContextFilter.java @@ -29,10 +29,7 @@ import jakarta.servlet.ServletException; import jakarta.servlet.ServletRequest; import jakarta.servlet.ServletResponse; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; -import org.apache.activemq.web.BrokerFacade; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.web.bind.ServletRequestDataBinder; @@ -60,101 +57,27 @@ * */ public class ApplicationContextFilter implements Filter { - private static final transient Logger LOG = LoggerFactory.getLogger(ApplicationContextFilter.class); + private static final Logger LOG = LoggerFactory.getLogger(ApplicationContextFilter.class); private ServletContext servletContext; - private String applicationContextName = "applicationContext"; private String requestContextName = "requestContext"; - private String requestName = "request"; public void init(FilterConfig config) throws ServletException { this.servletContext = config.getServletContext(); - this.applicationContextName = getInitParameter(config, "applicationContextName", applicationContextName); this.requestContextName = getInitParameter(config, "requestContextName", requestContextName); - this.requestName = getInitParameter(config, "requestName", requestName); - // register the application context in the applicationScope - WebApplicationContext context = WebApplicationContextUtils.getWebApplicationContext(servletContext); - Map wrapper = createApplicationContextWrapper(context); - servletContext.setAttribute(applicationContextName, wrapper); + LOG.info("Application Context Filter initialized. Request context is available in '{}'", requestContextName); } - public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { - // lets register a requestContext in the requestScope - Map requestContextWrapper = createRequestContextWrapper(request); - String path = ((HttpServletRequest)request).getRequestURI(); - // handle slave brokers -// try { -// if ( !(path.endsWith("css") || path.endsWith("png") || path.endsWith("ico") || path.endsWith(slavePage)) -// && ((BrokerFacade)requestContextWrapper.get("brokerQuery")).isSlave()) { -// ((HttpServletResponse)response).sendRedirect(slavePage); -// return; -// } -// } catch (Exception e) { -// LOG.warn(path + ", failed to access BrokerFacade: reason: " + e.getLocalizedMessage()); -// if (LOG.isDebugEnabled()) { -// LOG.debug(request.toString(), e); -// } -// throw new IOException(e); -// } - request.setAttribute(requestContextName, requestContextWrapper); - request.setAttribute(requestName, request); - chain.doFilter(request, response); - } - - public void destroy() { - } - - public ServletContext getServletContext() { - return servletContext; - } - - public String getApplicationContextName() { - return applicationContextName; - } - - public void setApplicationContextName(String variableName) { - this.applicationContextName = variableName; - } - - public String getRequestContextName() { - return requestContextName; - } - - public void setRequestContextName(String requestContextName) { - this.requestContextName = requestContextName; - } - - protected String getInitParameter(FilterConfig config, String key, String defaultValue) { + private String getInitParameter(final FilterConfig config, final String key, final String defaultValue) { String parameter = config.getInitParameter(key); return (parameter != null) ? parameter : defaultValue; } - /** - * Creates a wrapper around the web application context so that it can be - * accessed easily from inside JSP EL (or other expression languages in - * other view technologies). - */ - protected Map createApplicationContextWrapper(final WebApplicationContext context) { - Map wrapper = new AbstractMap() { - - public WebApplicationContext getContext() { - return context; - } - - public Object get(Object key) { - if (key == null) { - return null; - } - return context.getBean(key.toString()); - } - - public Set entrySet() { - return Collections.EMPTY_SET; - } - - }; - return wrapper; + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { + // lets register a requestContext in the requestScope + request.setAttribute(requestContextName, createRequestContextWrapper(request)); + chain.doFilter(request, response); } /** @@ -163,28 +86,21 @@ public Set entrySet() { * accessed easily from inside JSP EL (or other expression languages in * other view technologies). */ - protected Map createRequestContextWrapper(final ServletRequest request) { + private Map createRequestContextWrapper(final ServletRequest request) { final WebApplicationContext context = WebApplicationContextUtils.getWebApplicationContext(servletContext); - Map wrapper = new AbstractMap() { - - public WebApplicationContext getContext() { - return context; - } - + return new AbstractMap<>() { public Object get(Object key) { if (key == null) { return null; } - return bindRequestBean(context.getBean(key.toString()), request); + final Object emptyBean = context.getBean(key.toString()); + return bindRequestBean(emptyBean, request); } public Set entrySet() { return Collections.EMPTY_SET; } - }; - return wrapper; - } /** @@ -197,5 +113,4 @@ protected Object bindRequestBean(Object bean, ServletRequest request) { binder.bind(request); return bean; } - } diff --git a/activemq-web-console/src/main/java/org/apache/activemq/web/filter/CSRFFilter.java b/activemq-web-console/src/main/java/org/apache/activemq/web/filter/CSRFFilter.java new file mode 100644 index 00000000000..5113b6c7366 --- /dev/null +++ b/activemq-web-console/src/main/java/org/apache/activemq/web/filter/CSRFFilter.java @@ -0,0 +1,45 @@ +/** + * 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.activemq.web.filter; + +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpFilter; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import org.apache.activemq.web.SessionFilter; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; + +public class CSRFFilter extends HttpFilter { + + private static final Logger LOG = LoggerFactory.getLogger(CSRFFilter.class); + + @Override + public void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException { + final Object sessionSecret = request.getSession().getAttribute(SessionFilter.SESSION_SECRET_ATTRIBUTE); + if (sessionSecret == null || !sessionSecret.equals(request.getParameter("secret"))) { + throw new UnsupportedOperationException("Possible CSRF attack"); + } + + LOG.info("CSRF Token validated successfully"); + + chain.doFilter(request, response); + } +} diff --git a/activemq-web-console/src/main/java/org/apache/activemq/web/handler/BindingBeanNameUrlHandlerMapping.java b/activemq-web-console/src/main/java/org/apache/activemq/web/handler/BindingBeanNameUrlHandlerMapping.java deleted file mode 100644 index 9f8caf4bfb3..00000000000 --- a/activemq-web-console/src/main/java/org/apache/activemq/web/handler/BindingBeanNameUrlHandlerMapping.java +++ /dev/null @@ -1,79 +0,0 @@ -/** - * 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.activemq.web.handler; - -import java.util.Arrays; - -import jakarta.servlet.http.HttpServletRequest; - -import org.apache.activemq.web.DestinationFacade; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.web.bind.ServletRequestDataBinder; -import org.springframework.web.servlet.HandlerExecutionChain; -import org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping; - -/** - * - */ -public class BindingBeanNameUrlHandlerMapping extends BeanNameUrlHandlerMapping { - private static final transient Logger LOG = LoggerFactory.getLogger(BindingBeanNameUrlHandlerMapping.class); - - @Override - protected Object getHandlerInternal(HttpServletRequest request) throws Exception { - Object object = super.getHandlerInternal(request); - - if (object instanceof String) { - String handlerName = (String) object; - object = getApplicationContext().getBean(handlerName); - } - if (object instanceof HandlerExecutionChain) { - HandlerExecutionChain handlerExecutionChain = (HandlerExecutionChain) object; - object = handlerExecutionChain.getHandler(); - } - - if (object != null) { - // prevent CSRF attacks - if (object instanceof DestinationFacade) { - // check supported methods - if (!Arrays.asList(((DestinationFacade)object).getSupportedHttpMethods()).contains(request.getMethod())) { - throw new UnsupportedOperationException("Unsupported method " + request.getMethod() + " for path " + request.getRequestURI()); - } - // check the 'secret' - if (request.getSession().getAttribute("secret") == null || - !request.getSession().getAttribute("secret").equals(request.getParameter("secret"))) { - throw new UnsupportedOperationException("Possible CSRF attack"); - } - } - - ServletRequestDataBinder binder = new ServletRequestDataBinder(object, "request"); - try { - binder.bind(request); - binder.setIgnoreUnknownFields(true); - if (LOG.isDebugEnabled()) { - LOG.debug("Bound POJO is now: " + object); - } - } - catch (Exception e) { - LOG.warn("Caught: " + e, e); - throw e; - } - } - - return object; - } -} diff --git a/activemq-web-console/src/main/webapp/WEB-INF/dispatcher-servlet.xml b/activemq-web-console/src/main/webapp/WEB-INF/dispatcher-servlet.xml deleted file mode 100644 index 9e36e16011f..00000000000 --- a/activemq-web-console/src/main/webapp/WEB-INF/dispatcher-servlet.xml +++ /dev/null @@ -1,68 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/activemq-web-console/src/main/webapp/WEB-INF/web.xml b/activemq-web-console/src/main/webapp/WEB-INF/web.xml index d67e9d006de..75e1e228e42 100644 --- a/activemq-web-console/src/main/webapp/WEB-INF/web.xml +++ b/activemq-web-console/src/main/webapp/WEB-INF/web.xml @@ -34,11 +34,21 @@ org.apache.activemq.web.filter.ApplicationContextFilter + + csrf + org.apache.activemq.web.filter.CSRFFilter + + spring /* + + csrf + *.action + + QueueBrowseServlet @@ -87,18 +97,14 @@ org.apache.activemq.web.WebConsoleStarter - - - - - dispatcher - org.springframework.web.servlet.DispatcherServlet + actionServlet + org.apache.activemq.web.ActionServlet 2 - dispatcher + actionServlet *.action diff --git a/activemq-web-console/src/main/webapp/WEB-INF/webconsole-query.xml b/activemq-web-console/src/main/webapp/WEB-INF/webconsole-common.xml similarity index 51% rename from activemq-web-console/src/main/webapp/WEB-INF/webconsole-query.xml rename to activemq-web-console/src/main/webapp/WEB-INF/webconsole-common.xml index 6ec95ca12c4..d35e59973cf 100644 --- a/activemq-web-console/src/main/webapp/WEB-INF/webconsole-query.xml +++ b/activemq-web-console/src/main/webapp/WEB-INF/webconsole-common.xml @@ -16,13 +16,9 @@ limitations under the License. --> + xmlns:context="http://www.springframework.org/schema/context" + xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd + http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> - - - - - - - + diff --git a/activemq-web-console/src/main/webapp/WEB-INF/webconsole-embedded.xml b/activemq-web-console/src/main/webapp/WEB-INF/webconsole-embedded.xml index 5e487ac3c49..4f65cb862fa 100644 --- a/activemq-web-console/src/main/webapp/WEB-INF/webconsole-embedded.xml +++ b/activemq-web-console/src/main/webapp/WEB-INF/webconsole-embedded.xml @@ -20,7 +20,7 @@ xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd"> - + diff --git a/activemq-web-console/src/main/webapp/WEB-INF/webconsole-invm.xml b/activemq-web-console/src/main/webapp/WEB-INF/webconsole-invm.xml index e766e8aecab..9e87873b5ee 100644 --- a/activemq-web-console/src/main/webapp/WEB-INF/webconsole-invm.xml +++ b/activemq-web-console/src/main/webapp/WEB-INF/webconsole-invm.xml @@ -20,7 +20,7 @@ xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd"> - + diff --git a/activemq-web-console/src/main/webapp/WEB-INF/webconsole-jndi.xml b/activemq-web-console/src/main/webapp/WEB-INF/webconsole-jndi.xml index 84148a0001c..8b1876d2a99 100644 --- a/activemq-web-console/src/main/webapp/WEB-INF/webconsole-jndi.xml +++ b/activemq-web-console/src/main/webapp/WEB-INF/webconsole-jndi.xml @@ -20,7 +20,7 @@ xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd"> - + diff --git a/activemq-web-console/src/main/webapp/WEB-INF/webconsole-osgi.xml b/activemq-web-console/src/main/webapp/WEB-INF/webconsole-osgi.xml index 1a3cbfbf816..ae2bd715db6 100644 --- a/activemq-web-console/src/main/webapp/WEB-INF/webconsole-osgi.xml +++ b/activemq-web-console/src/main/webapp/WEB-INF/webconsole-osgi.xml @@ -20,7 +20,7 @@ xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd"> - + diff --git a/activemq-web-console/src/main/webapp/WEB-INF/webconsole-properties.xml b/activemq-web-console/src/main/webapp/WEB-INF/webconsole-properties.xml index eb42b4f4819..db419d44b71 100644 --- a/activemq-web-console/src/main/webapp/WEB-INF/webconsole-properties.xml +++ b/activemq-web-console/src/main/webapp/WEB-INF/webconsole-properties.xml @@ -20,7 +20,7 @@ xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd"> - + diff --git a/activemq-web-console/src/main/webapp/test/index.jsp b/activemq-web-console/src/main/webapp/test/index.jsp index 65719d442c1..1f2b9de4441 100644 --- a/activemq-web-console/src/main/webapp/test/index.jsp +++ b/activemq-web-console/src/main/webapp/test/index.jsp @@ -63,10 +63,6 @@ These pages are used to test out the environment and web framework. request.serverPort ${request.serverPort} - - Spring applicationContext - ${applicationContext} - Spring requestContext ${requestContext} diff --git a/activemq-web/pom.xml b/activemq-web/pom.xml index 43782fcde95..d590750bf78 100644 --- a/activemq-web/pom.xml +++ b/activemq-web/pom.xml @@ -98,11 +98,7 @@ org.apache.xbean xbean-spring - - org.springframework - spring-webmvc - false - + org.springframework spring-web diff --git a/activemq-web/src/main/java/org/apache/activemq/web/ConnectionQuery.java b/activemq-web/src/main/java/org/apache/activemq/web/ConnectionQuery.java index 27d53341403..bdc224b520e 100644 --- a/activemq-web/src/main/java/org/apache/activemq/web/ConnectionQuery.java +++ b/activemq-web/src/main/java/org/apache/activemq/web/ConnectionQuery.java @@ -21,12 +21,16 @@ import org.apache.activemq.broker.jmx.ConnectionViewMBean; import org.apache.activemq.broker.jmx.SubscriptionViewMBean; +import org.springframework.stereotype.Component; +import org.springframework.web.context.annotation.RequestScope; /** * Query for a single connection. * * @author ms */ +@Component("connectionQuery") +@RequestScope public class ConnectionQuery { private final BrokerFacade mBrokerFacade; diff --git a/activemq-web/src/main/java/org/apache/activemq/web/DestinationFacade.java b/activemq-web/src/main/java/org/apache/activemq/web/DestinationFacade.java index ac00500ddb1..8527cac96fa 100644 --- a/activemq-web/src/main/java/org/apache/activemq/web/DestinationFacade.java +++ b/activemq-web/src/main/java/org/apache/activemq/web/DestinationFacade.java @@ -16,21 +16,16 @@ */ package org.apache.activemq.web; -import jakarta.servlet.http.HttpServletRequest; - import org.apache.activemq.broker.jmx.BrokerViewMBean; import org.apache.activemq.broker.jmx.QueueViewMBean; import org.apache.activemq.command.ActiveMQDestination; -import org.springframework.web.servlet.ModelAndView; -/** - * - */ public class DestinationFacade { private String jmsDestination; private String jmsDestinationType; - private BrokerFacade brokerFacade; + + private final BrokerFacade brokerFacade; public DestinationFacade(BrokerFacade brokerFacade) { this.brokerFacade = brokerFacade; @@ -119,19 +114,6 @@ protected QueueViewMBean getQueueView() throws Exception { return getBrokerFacade().getQueue(name); } - protected ModelAndView redirectToRequest(HttpServletRequest request) { - String view = "redirect:" + request.getRequestURI(); - return new ModelAndView(view); - } - - protected ModelAndView redirectToBrowseView() { - return new ModelAndView("redirect:" + (isQueue() ? "queues.jsp" : "topics.jsp")); - } - - protected ModelAndView redirectToDestinationView() { - return new ModelAndView("redirect:browse.jsp?JMSDestination=" + jmsDestination); - } - protected String getPhysicalDestinationName() { return createDestination().getPhysicalName(); } diff --git a/activemq-web/src/main/java/org/apache/activemq/web/MessageQuery.java b/activemq-web/src/main/java/org/apache/activemq/web/MessageQuery.java index e9daf59df6e..c3eddb977cb 100644 --- a/activemq-web/src/main/java/org/apache/activemq/web/MessageQuery.java +++ b/activemq-web/src/main/java/org/apache/activemq/web/MessageQuery.java @@ -27,12 +27,16 @@ import java.util.Enumeration; import java.util.HashMap; import java.util.Map; +import org.springframework.stereotype.Component; +import org.springframework.web.context.annotation.RequestScope; /** * Allow the user to browse a message on a queue by its ID * * */ +@Component("messageQuery") +@RequestScope public class MessageQuery extends QueueBrowseQuery { private String id; diff --git a/activemq-web/src/main/java/org/apache/activemq/web/QueueBrowseQuery.java b/activemq-web/src/main/java/org/apache/activemq/web/QueueBrowseQuery.java index 7965b272c54..9f256ac479e 100644 --- a/activemq-web/src/main/java/org/apache/activemq/web/QueueBrowseQuery.java +++ b/activemq-web/src/main/java/org/apache/activemq/web/QueueBrowseQuery.java @@ -17,6 +17,8 @@ package org.apache.activemq.web; import org.springframework.beans.factory.DisposableBean; +import org.springframework.stereotype.Component; +import org.springframework.web.context.annotation.RequestScope; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; @@ -25,10 +27,8 @@ import jakarta.jms.QueueBrowser; import jakarta.jms.Session; -/** - * - * - */ +@Component("queueBrowser") +@RequestScope public class QueueBrowseQuery extends DestinationFacade implements DisposableBean { private String selector; private Queue queue; diff --git a/activemq-web/src/main/java/org/apache/activemq/web/QueueConsumerQuery.java b/activemq-web/src/main/java/org/apache/activemq/web/QueueConsumerQuery.java index ae744c4c139..58dea9b70a0 100644 --- a/activemq-web/src/main/java/org/apache/activemq/web/QueueConsumerQuery.java +++ b/activemq-web/src/main/java/org/apache/activemq/web/QueueConsumerQuery.java @@ -21,12 +21,16 @@ import jakarta.jms.JMSException; import org.apache.activemq.broker.jmx.SubscriptionViewMBean; +import org.springframework.stereotype.Component; +import org.springframework.web.context.annotation.RequestScope; /** * Query for Queue consumers. - * + * * */ +@Component("queueConsumerQuery") +@RequestScope public class QueueConsumerQuery extends DestinationFacade { public QueueConsumerQuery(BrokerFacade brokerFacade) throws JMSException { diff --git a/activemq-web/src/main/java/org/apache/activemq/web/QueueProducerQuery.java b/activemq-web/src/main/java/org/apache/activemq/web/QueueProducerQuery.java index 4137ca12b29..4eb7772a130 100644 --- a/activemq-web/src/main/java/org/apache/activemq/web/QueueProducerQuery.java +++ b/activemq-web/src/main/java/org/apache/activemq/web/QueueProducerQuery.java @@ -21,12 +21,16 @@ import jakarta.jms.JMSException; import org.apache.activemq.broker.jmx.ProducerViewMBean; +import org.springframework.stereotype.Component; +import org.springframework.web.context.annotation.RequestScope; /** * Query for Queue producers. * * */ +@Component("queueProducerQuery") +@RequestScope public class QueueProducerQuery extends DestinationFacade { public QueueProducerQuery(BrokerFacade brokerFacade) throws JMSException { diff --git a/activemq-web/src/main/java/org/apache/activemq/web/SessionFilter.java b/activemq-web/src/main/java/org/apache/activemq/web/SessionFilter.java index e421bed1251..ea945a4f0de 100644 --- a/activemq-web/src/main/java/org/apache/activemq/web/SessionFilter.java +++ b/activemq-web/src/main/java/org/apache/activemq/web/SessionFilter.java @@ -36,12 +36,14 @@ */ public class SessionFilter implements Filter { + public static final String SESSION_SECRET_ATTRIBUTE = "secret"; + public void init(FilterConfig filterConfig) throws ServletException { } public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { // set secret to prevent CSRF attacks - ((HttpServletRequest)request).getSession(true).setAttribute("secret", UUID.randomUUID().toString());; + ((HttpServletRequest)request).getSession(true).setAttribute(SESSION_SECRET_ATTRIBUTE, UUID.randomUUID().toString());; chain.doFilter(request, response); } diff --git a/activemq-web/src/main/java/org/apache/activemq/web/TopicProducerQuery.java b/activemq-web/src/main/java/org/apache/activemq/web/TopicProducerQuery.java index ef375cb9819..1d0412747b2 100644 --- a/activemq-web/src/main/java/org/apache/activemq/web/TopicProducerQuery.java +++ b/activemq-web/src/main/java/org/apache/activemq/web/TopicProducerQuery.java @@ -21,12 +21,16 @@ import jakarta.jms.JMSException; import org.apache.activemq.broker.jmx.ProducerViewMBean; +import org.springframework.stereotype.Component; +import org.springframework.web.context.annotation.RequestScope; /** * Query for Topic producers. * * */ +@Component("topicProducerQuery") +@RequestScope public class TopicProducerQuery extends DestinationFacade { public TopicProducerQuery(BrokerFacade brokerFacade) throws JMSException { diff --git a/activemq-web/src/main/java/org/apache/activemq/web/TopicSubscriberQuery.java b/activemq-web/src/main/java/org/apache/activemq/web/TopicSubscriberQuery.java index cf485557082..bbfee580968 100644 --- a/activemq-web/src/main/java/org/apache/activemq/web/TopicSubscriberQuery.java +++ b/activemq-web/src/main/java/org/apache/activemq/web/TopicSubscriberQuery.java @@ -21,12 +21,16 @@ import jakarta.jms.JMSException; import org.apache.activemq.broker.jmx.SubscriptionViewMBean; +import org.springframework.stereotype.Component; +import org.springframework.web.context.annotation.RequestScope; /** * Query for Topic producers. * * */ +@Component("topicSubscriberQuery") +@RequestScope public class TopicSubscriberQuery extends DestinationFacade { public TopicSubscriberQuery(BrokerFacade brokerFacade) throws JMSException { diff --git a/assembly/src/release/webapps/admin/WEB-INF/webconsole-embedded.xml b/assembly/src/release/webapps/admin/WEB-INF/webconsole-embedded.xml index 1b87abe275f..898f588a0d9 100644 --- a/assembly/src/release/webapps/admin/WEB-INF/webconsole-embedded.xml +++ b/assembly/src/release/webapps/admin/WEB-INF/webconsole-embedded.xml @@ -19,7 +19,7 @@ xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd"> - +