Initial import of a simple web based console for ActiveMQ

git-svn-id: https://svn.apache.org/repos/asf/incubator/activemq/trunk@397209 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
James Strachan 2006-04-26 14:45:03 +00:00
parent d680ba1291
commit 90b66ce627
65 changed files with 8960 additions and 0 deletions

View File

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src/main/java"/>
<classpathentry kind="src" path="src/main/webapp"/>
<classpathentry kind="src" path="src/main/resources"/>
<classpathentry output="target/test-classes" kind="src" path="src/test/java"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="var" path="M2_REPO/mx4j/mx4j/2.1.1/mx4j-2.1.1.jar"/>
<classpathentry kind="var" path="M2_REPO/org/mortbay/jetty/jetty/6.0.0beta14/jetty-6.0.0beta14.jar"/>
<classpathentry kind="var" path="M2_REPO/jdom/jdom/1.0/jdom-1.0.jar"/>
<classpathentry kind="var" path="M2_REPO/org/apache/geronimo/specs/geronimo-jms_1.1_spec/1.0/geronimo-jms_1.1_spec-1.0.jar"/>
<classpathentry kind="var" path="M2_REPO/xstream/xstream/1.1.2/xstream-1.1.2.jar"/>
<classpathentry kind="var" path="M2_REPO/org/mortbay/jetty/jetty-util/6.0.0beta14/jetty-util-6.0.0beta14.jar"/>
<classpathentry kind="var" path="M2_REPO/ant/ant/1.6.2/ant-1.6.2.jar"/>
<classpathentry kind="var" path="M2_REPO/rome/rome/0.8/rome-0.8.jar"/>
<classpathentry kind="var" path="M2_REPO/org/slf4j/slf4j-jcl/1.0-rc5/slf4j-jcl-1.0-rc5.jar"/>
<classpathentry kind="var" path="M2_REPO/org/apache/xbean/xbean-spring/2.2/xbean-spring-2.2.jar"/>
<classpathentry kind="var" path="M2_REPO/incubator-activemq/activemq-jaas/4.0-SNAPSHOT/activemq-jaas-4.0-SNAPSHOT.jar"/>
<classpathentry kind="var" path="M2_REPO/javax/servlet/jstl/1.0/jstl-1.0.jar"/>
<classpathentry kind="var" path="M2_REPO/incubator-activemq/activeio-core/3.0-SNAPSHOT/activeio-core-3.0-SNAPSHOT.jar"/>
<classpathentry kind="var" path="M2_REPO/xmlpull/xmlpull/1.1.3.4d_b4_min/xmlpull-1.1.3.4d_b4_min.jar"/>
<classpathentry kind="var" path="M2_REPO/stax/stax-api/1.0/stax-api-1.0.jar"/>
<classpathentry kind="var" path="M2_REPO/org/springframework/spring/1.2.6/spring-1.2.6.jar"/>
<classpathentry kind="var" path="M2_REPO/backport-util-concurrent/backport-util-concurrent/2.1/backport-util-concurrent-2.1.jar"/>
<classpathentry kind="var" path="M2_REPO/org/apache/geronimo/specs/geronimo-j2ee-management_1.0_spec/1.0/geronimo-j2ee-management_1.0_spec-1.0.jar"/>
<classpathentry kind="var" path="M2_REPO/org/mortbay/jetty/servlet-api-2.5/6.0.0beta14/servlet-api-2.5-6.0.0beta14.jar"/>
<classpathentry kind="var" path="M2_REPO/junit/junit/3.8.1/junit-3.8.1.jar"/>
<classpathentry kind="var" path="M2_REPO/org/apache/geronimo/specs/geronimo-jta_1.0.1B_spec/1.0/geronimo-jta_1.0.1B_spec-1.0.jar"/>
<classpathentry kind="var" path="M2_REPO/taglibs/standard/1.1.2/standard-1.1.2.jar"/>
<classpathentry kind="var" path="M2_REPO/org/apache/geronimo/specs/geronimo-j2ee-jacc_1.0_spec/1.0/geronimo-j2ee-jacc_1.0_spec-1.0.jar"/>
<classpathentry kind="var" path="M2_REPO/org/apache/derby/derby/10.1.1.0/derby-10.1.1.0.jar"/>
<classpathentry kind="var" path="M2_REPO/opensymphony/sitemesh/2.2.1/sitemesh-2.2.1.jar"/>
<classpathentry kind="var" path="M2_REPO/commons-logging/commons-logging/1.0.3/commons-logging-1.0.3.jar"/>
<classpathentry kind="var" path="M2_REPO/qdox/qdox/1.5/qdox-1.5.jar"/>
<classpathentry combineaccessrules="false" kind="src" path="/activemq-core"/>
<classpathentry combineaccessrules="false" kind="src" path="/activemq-web"/>
<classpathentry kind="output" path="target/classes"/>
</classpath>

View File

@ -0,0 +1,14 @@
<projectDescription>
<name>activemq-web-console</name>
<comment>Web Console for ActiveMQ</comment>
<projects/>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments/>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>

View File

@ -0,0 +1,5 @@
#Wed Apr 26 13:41:43 BST 2006
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.4
org.eclipse.jdt.core.compiler.compliance=1.4
org.eclipse.jdt.core.compiler.source=1.4

View File

@ -0,0 +1,8 @@
Welcome to the ActiveMQ Web Console
To run the console, the jetty plugin may be used:
mvn jetty6:run

184
activemq-web-console/pom.xml Executable file
View File

@ -0,0 +1,184 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright 2005-2006 The Apache Software Foundation
Licensed 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.
-->
<project
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>incubator-activemq</groupId>
<artifactId>activemq-parent</artifactId>
<version>4.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>activemq-web-console</artifactId>
<packaging>war</packaging>
<name>ActiveMQ :: Web Console</name>
<description>Web Console for ActiveMQ</description>
<build>
<plugins>
<plugin>
<groupId>org.mortbay.jetty</groupId>
<artifactId>maven-jetty6-plugin</artifactId>
<configuration>
<systemProperties>
<!-- enable easy connection to JConsole -->
<systemProperty>
<name>com.sun.management.jmxremote</name>
<value></value>
</systemProperty>
</systemProperties>
<scanIntervalSeconds>10</scanIntervalSeconds>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.mortbay.jetty</groupId>
<artifactId>servlet-api-2.5</artifactId>
<scope>provided</scope>
</dependency>
<!-- j2ee jars -->
<dependency>
<groupId>org.apache.geronimo.specs</groupId>
<artifactId>geronimo-jms_1.1_spec</artifactId>
</dependency>
<dependency>
<groupId>org.apache.geronimo.specs</groupId>
<artifactId>geronimo-jta_1.0.1B_spec</artifactId>
</dependency>
<dependency>
<groupId>org.apache.geronimo.specs</groupId>
<artifactId>geronimo-j2ee-management_1.0_spec</artifactId>
</dependency>
<dependency>
<groupId>org.apache.geronimo.specs</groupId>
<artifactId>geronimo-j2ee-jacc_1.0_spec</artifactId>
</dependency>
<!-- activemq -->
<dependency>
<groupId>${pom.groupId}</groupId>
<artifactId>activemq-web</artifactId>
</dependency>
<!-- TODO this should not be needed, but transitive dependencies are not working -->
<dependency>
<groupId>${pom.groupId}</groupId>
<artifactId>activemq-core</artifactId>
</dependency>
<dependency>
<groupId>${pom.groupId}</groupId>
<artifactId>activeio-core</artifactId>
</dependency>
<dependency>
<groupId>incubator-activemq</groupId>
<artifactId>activemq-jaas</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring</artifactId>
</dependency>
<dependency>
<groupId>org.apache.xbean</groupId>
<artifactId>xbean-spring</artifactId>
</dependency>
<!-- web container -->
<dependency>
<groupId>org.mortbay.jetty</groupId>
<artifactId>jetty</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mortbay.jetty</groupId>
<artifactId>jetty-util</artifactId>
<scope>test</scope>
</dependency>
<!-- enable commons-logging when inside jetty6:run -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-jcl</artifactId>
<version>1.0-rc5</version>
<!--
<scope>optional</scope>
-->
</dependency>
<!-- SiteMesh for layout -->
<dependency>
<groupId>opensymphony</groupId>
<artifactId>sitemesh</artifactId>
<version>2.2.1</version>
</dependency>
<!-- JSTL support -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>1.1.2</version>
</dependency>
<!-- XStream marshalling -->
<dependency>
<groupId>xmlpull</groupId>
<artifactId>xmlpull</artifactId>
</dependency>
<dependency>
<groupId>xstream</groupId>
<artifactId>xstream</artifactId>
</dependency>
<!-- used for testing -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<!-- Derby SQL DB used for testing JDBC message store -->
<dependency>
<groupId>org.apache.derby</groupId>
<artifactId>derby</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,134 @@
/**
*
* Copyright 2005-2006 The Apache Software Foundation
*
* Licensed 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 org.apache.activemq.broker.Broker;
import org.apache.activemq.broker.BrokerService;
import org.apache.activemq.broker.jmx.BrokerView;
import org.apache.activemq.broker.jmx.BrokerViewMBean;
import org.apache.activemq.broker.jmx.DurableSubscriptionViewMBean;
import org.apache.activemq.broker.jmx.ManagedRegionBroker;
import org.apache.activemq.broker.jmx.ManagementContext;
import org.apache.activemq.broker.jmx.QueueViewMBean;
import org.apache.activemq.broker.jmx.TopicViewMBean;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import javax.management.MBeanServer;
import javax.management.MBeanServerInvocationHandler;
import javax.management.ObjectName;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
/**
*
* @version $Revision$
*/
public class BrokerFacade {
private static final Log log = LogFactory.getLog(BrokerFacade.class);
private BrokerService brokerService;
public BrokerFacade(BrokerService brokerService) {
this.brokerService = brokerService;
}
public BrokerService getBrokerService() {
return brokerService;
}
public Broker getBroker() throws Exception {
return brokerService.getBroker();
}
public ManagementContext getManagementContext() {
return brokerService.getManagementContext();
}
public BrokerViewMBean getBrokerAdmin() throws Exception {
// TODO could use JMX to look this up
return brokerService.getAdminView();
}
public ManagedRegionBroker getManagedBroker() throws Exception {
BrokerView adminView = brokerService.getAdminView();
if (adminView == null) {
return null;
}
return adminView.getBroker();
}
// TODO - we should not have to use JMX to implement the following methods...
public Collection getQueues() throws Exception {
BrokerView broker = brokerService.getAdminView();
if (broker == null) {
return Collections.EMPTY_LIST;
}
ObjectName[] queues = broker.getQueues();
return getManagedObjects(queues, QueueViewMBean.class);
}
public Collection getTopics() throws Exception {
BrokerView broker = brokerService.getAdminView();
if (broker == null) {
return Collections.EMPTY_LIST;
}
ObjectName[] queues = broker.getTopics();
return getManagedObjects(queues, TopicViewMBean.class);
}
public Collection getDurableTopicSubscribers() throws Exception {
BrokerView broker = brokerService.getAdminView();
if (broker == null) {
return Collections.EMPTY_LIST;
}
ObjectName[] queues = broker.getDurableTopicSubscribers();
return getManagedObjects(queues, DurableSubscriptionViewMBean.class);
}
protected Collection getManagedObjects(ObjectName[] names, Class type) {
List answer = new ArrayList();
MBeanServer mbeanServer = getManagementContext().getMBeanServer();
if (mbeanServer != null) {
for (int i = 0; i < names.length; i++) {
ObjectName name = names[i];
Object value = MBeanServerInvocationHandler.newProxyInstance(mbeanServer, name, type, true);
if (value != null) {
answer.add(value);
}
}
}
return answer;
}
/**
* public Collection getQueues() throws Exception { ManagedRegionBroker
* broker = getManagedBroker(); if (broker == null) { return new
* ArrayList(); } return
* broker.getQueueRegion().getDestinationMap().values(); }
*
*
* public Collection getTopics() throws Exception { ManagedRegionBroker
* broker = getManagedBroker(); if (broker == null) { return new
* ArrayList(); } return
* broker.getTopicRegion().getDestinationMap().values(); }
*/
}

View File

@ -0,0 +1,121 @@
/**
*
* Copyright 2005-2006 The Apache Software Foundation
*
* Licensed 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 org.apache.activemq.broker.BrokerService;
import org.apache.activemq.command.ActiveMQDestination;
import org.apache.activemq.command.ActiveMQQueue;
import org.apache.activemq.command.ActiveMQTopic;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
/**
*
* @version $Revision$
*/
public class DestinationFacade extends BrokerFacade {
private String JMSDestination;
private String JMSDestinationType;
public DestinationFacade(BrokerService brokerService) {
super(brokerService);
}
public String toString() {
return super.toString() + "[destination:" + JMSDestination + "; type=" + JMSDestinationType + "]";
}
// Operations
// -------------------------------------------------------------------------
public void removeDestination() throws Exception {
getValidDestination();
if (isQueue()) {
getBrokerAdmin().removeQueue(getJMSDestination());
}
else {
getBrokerAdmin().removeTopic(getJMSDestination());
}
}
public void addDestination() throws Exception {
if (isQueue()) {
getBrokerAdmin().addQueue(getValidDestination());
}
else {
getBrokerAdmin().addTopic(getValidDestination());
}
}
// Properties
// -------------------------------------------------------------------------
public boolean isQueue() {
if (JMSDestinationType != null && JMSDestinationType.equalsIgnoreCase("topic")) {
return false;
}
return true;
}
public String getJMSDestination() {
return JMSDestination;
}
public void setJMSDestination(String destination) {
this.JMSDestination = destination;
}
public String getJMSDestinationType() {
return JMSDestinationType;
}
public void setJMSDestinationType(String type) {
this.JMSDestinationType = type;
}
protected ActiveMQDestination createDestination() {
if (isQueue()) {
return new ActiveMQQueue(getValidDestination());
}
else {
return new ActiveMQTopic(getValidDestination());
}
}
protected String getValidDestination() {
if (JMSDestination == null) {
throw new IllegalArgumentException("No JMSDestination parameter specified");
}
return JMSDestination;
}
protected ModelAndView redirectToRequest(HttpServletRequest request) {
String view = "redirect:" + request.getRequestURI();
System.out.println("Redirecting to: " + view);
return new ModelAndView(view);
}
protected ModelAndView redirectToBrowseView() {
return new ModelAndView("redirect:" + (isQueue() ? "queues.jsp" : "topics.jsp"));
}
}

View File

@ -0,0 +1,50 @@
/**
*
* Copyright 2005-2006 The Apache Software Foundation
*
* Licensed 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 org.apache.activemq.broker.BrokerService;
/**
*
* @version $Revision$
*/
public class DurableSubscriberFacade extends DestinationFacade {
private String clientId;
private String subscriberName;
public DurableSubscriberFacade(BrokerService brokerService) {
super(brokerService);
}
public String getClientId() {
return clientId;
}
public void setClientId(String clientId) {
this.clientId = clientId;
}
public String getSubscriberName() {
return subscriberName;
}
public void setSubscriberName(String subscriberName) {
this.subscriberName = subscriberName;
}
}

View File

@ -0,0 +1,96 @@
/**
*
* Copyright 2005-2006 The Apache Software Foundation
*
* Licensed 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 org.apache.activemq.broker.BrokerService;
import org.springframework.beans.factory.DisposableBean;
import javax.jms.JMSException;
import javax.jms.Queue;
import javax.jms.QueueBrowser;
import javax.jms.Session;
/**
*
* @version $Revision$
*/
public class QueueBrowseQuery extends DestinationFacade implements DisposableBean {
private SessionPool sessionPool;
private String selector;
private Session session;
private Queue queue;
private QueueBrowser browser;
public QueueBrowseQuery(BrokerService brokerService, SessionPool sessionPool) throws JMSException {
super(brokerService);
this.sessionPool = sessionPool;
this.session = sessionPool.borrowSession();
}
public void destroy() throws Exception {
if (browser != null) {
browser.close();
}
sessionPool.returnSession(session);
session = null;
}
public QueueBrowser getBrowser() throws JMSException {
if (browser == null) {
browser = createBrowser();
}
return browser;
}
public void setBrowser(QueueBrowser browser) {
this.browser = browser;
}
public Queue getQueue() throws JMSException {
if (queue == null) {
queue = session.createQueue(getValidDestination());
}
return queue;
}
public void setQueue(Queue queue) {
this.queue = queue;
}
public String getSelector() {
return selector;
}
public void setSelector(String selector) {
this.selector = selector;
}
public Session getSession() {
return session;
}
public boolean isQueue() {
return true;
}
protected QueueBrowser createBrowser() throws JMSException {
return getSession().createBrowser(getQueue(), getSelector());
}
}

View File

@ -0,0 +1,88 @@
/*
* Copyright 2005-2006 The Apache Software Foundation.
*
* Licensed 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 org.apache.activemq.ActiveMQConnectionFactory;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.JMSException;
import javax.jms.Session;
import java.util.LinkedList;
/**
* A simple pool of JMS Session objects intended for use by Queue browsers.
*
* @version $Revision$
*/
public class SessionPool {
private ConnectionFactory connectionFactory;
private Connection connection;
private LinkedList sessions = new LinkedList();
public Connection getConnection() throws JMSException {
if (connection == null) {
connection = getConnectionFactory().createConnection();
connection.start();
}
return connection;
}
public void setConnection(Connection connection) {
this.connection = connection;
}
public ConnectionFactory getConnectionFactory() {
if (connectionFactory == null) {
// TODO support remote brokers too
connectionFactory = new ActiveMQConnectionFactory("vm://localhost");
}
return connectionFactory;
}
public void setConnectionFactory(ConnectionFactory connectionFactory) {
this.connectionFactory = connectionFactory;
}
public Session borrowSession() throws JMSException {
Session answer = null;
synchronized (sessions) {
if (sessions.isEmpty()) {
answer = createSession();
}
else {
answer = (Session) sessions.removeLast();
}
}
return answer;
}
protected void returnSession(Session session) {
if (session != null) {
synchronized (sessions) {
sessions.add(session);
}
}
}
protected Session createSession() throws JMSException {
return getConnection().createSession(false, Session.AUTO_ACKNOWLEDGE);
}
}

View File

@ -0,0 +1,43 @@
/**
*
* Copyright 2005-2006 The Apache Software Foundation
*
* Licensed 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 org.apache.activemq.broker.BrokerService;
import org.apache.activemq.web.DestinationFacade;
import org.apache.activemq.web.DurableSubscriberFacade;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
*
* @version $Revision$
*/
public class CreateDestination extends DestinationFacade implements Controller {
public CreateDestination(BrokerService brokerService) {
super(brokerService);
}
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
addDestination();
return redirectToBrowseView();
}
}

View File

@ -0,0 +1,54 @@
/**
*
* Copyright 2005-2006 The Apache Software Foundation
*
* Licensed 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 org.apache.activemq.broker.BrokerService;
import org.apache.activemq.web.DurableSubscriberFacade;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
*
* @version $Revision$
*/
public class CreateSubscriber extends DurableSubscriberFacade implements Controller {
private String selector;
public CreateSubscriber(BrokerService brokerService) {
super(brokerService);
}
public String getSelector() {
return selector;
}
public void setSelector(String selector) {
this.selector = selector;
}
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
if (selector != null && selector.length() == 0) {
selector = null;
}
getBrokerAdmin().createDurableSubscriber(getClientId(), getSubscriberName(), getValidDestination(), selector);
return new ModelAndView("redirect:subscribers.jsp");
}
}

View File

@ -0,0 +1,44 @@
/**
*
* Copyright 2005-2006 The Apache Software Foundation
*
* Licensed 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 org.apache.activemq.broker.BrokerService;
import org.apache.activemq.web.DestinationFacade;
import org.apache.activemq.web.DurableSubscriberFacade;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
*
* @version $Revision$
*/
public class DeleteDestination extends DestinationFacade implements Controller {
public DeleteDestination(BrokerService brokerService) {
super(brokerService);
}
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
removeDestination();
return redirectToBrowseView();
}
}

View File

@ -0,0 +1,42 @@
/**
*
* Copyright 2005-2006 The Apache Software Foundation
*
* Licensed 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 org.apache.activemq.broker.BrokerService;
import org.apache.activemq.web.DurableSubscriberFacade;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
*
* @version $Revision$
*/
public class DeleteSubscriber extends DurableSubscriberFacade implements Controller {
public DeleteSubscriber(BrokerService brokerService) {
super(brokerService);
}
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
getBrokerAdmin().destroyDurableSubscriber(getClientId(), getSubscriberName());
return new ModelAndView("redirect:subscribers.jsp");
}
}

View File

@ -0,0 +1,199 @@
/**
*
* Copyright 2005-2006 The Apache Software Foundation
*
* Licensed 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 org.apache.activemq.broker.BrokerService;
import org.apache.activemq.command.ActiveMQDestination;
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 javax.jms.JMSException;
import javax.jms.Message;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Iterator;
import java.util.Map;
/**
* Sends a message
*
* @version $Revision$
*/
public class SendMessage extends DestinationFacade implements Controller {
private String JMSText;
private boolean JMSPersistent;
private int JMSPriority;
private int JMSTimeToLive = -1;
private String JMSCorrelationID;
private String JMSReplyTo;
private String JMSType;
private int JMSMessageCount = 1;
private String JMSMessageCountHeader = "JMSXMessageNumber";
private boolean redirectToBrowse;
public SendMessage(BrokerService brokerService) {
super(brokerService);
}
public ModelAndView handleRequest(HttpServletRequest request, 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();
}
protected void sendMessages(HttpServletRequest request, WebClient client, ActiveMQDestination dest) throws JMSException {
if (JMSMessageCount <= 1) {
JMSMessageCount = 1;
}
for (int i = 0; i < JMSMessageCount; i++) {
Message message = createMessage(client, request);
appendHeaders(message, request);
if (JMSMessageCount > 1) {
message.setIntProperty(JMSMessageCountHeader, i + 1);
}
client.send(dest, message, JMSPersistent, JMSPriority, JMSTimeToLive);
System.out.println("Sent message: " + message);
}
}
// Properties
// -------------------------------------------------------------------------
public String getJMSCorrelationID() {
return JMSCorrelationID;
}
public void setJMSCorrelationID(String correlationID) {
JMSCorrelationID = correlationID;
}
public String getJMSReplyTo() {
return JMSReplyTo;
}
public void setJMSReplyTo(String replyTo) {
JMSReplyTo = replyTo;
}
public String getJMSType() {
return JMSType;
}
public void setJMSType(String type) {
JMSType = type;
}
public boolean isJMSPersistent() {
return JMSPersistent;
}
public void setJMSPersistent(boolean persistent) {
this.JMSPersistent = persistent;
}
public int getJMSPriority() {
return JMSPriority;
}
public void setJMSPriority(int priority) {
this.JMSPriority = priority;
}
public String getJMSText() {
return JMSText;
}
public void setJMSText(String text) {
this.JMSText = text;
}
public int getJMSTimeToLive() {
return JMSTimeToLive;
}
public void setJMSTimeToLive(int timeToLive) {
this.JMSTimeToLive = timeToLive;
}
public int getJMSMessageCount() {
return JMSMessageCount;
}
public void setJMSMessageCount(int copies) {
JMSMessageCount = copies;
}
// Implementation methods
// -------------------------------------------------------------------------
protected Message createMessage(WebClient client, HttpServletRequest request) throws JMSException {
if (JMSText != null) {
return client.getSession().createTextMessage(JMSText);
}
// TODO create Bytes message from request body...
return client.getSession().createMessage();
}
protected void appendHeaders(Message message, HttpServletRequest request) throws JMSException {
message.setJMSCorrelationID(JMSCorrelationID);
if (JMSReplyTo != null) {
message.setJMSReplyTo(ActiveMQDestination.createDestination(JMSReplyTo, ActiveMQDestination.QUEUE_TYPE));
}
message.setJMSType(JMSType);
// now lets add all of the parameters
Map map = request.getParameterMap();
if (map != null) {
for (Iterator iter = map.entrySet().iterator(); iter.hasNext();) {
Map.Entry entry = (Map.Entry) iter.next();
String name = (String) entry.getKey();
Object value = entry.getValue();
if (isValidPropertyName(name)) {
if (value instanceof String[]) {
String[] array = (String[]) value;
if (array.length > 0) {
value = array[0];
}
else {
value = null;
}
}
if (value != null) {
message.setObjectProperty(name, value);
}
}
}
}
}
protected boolean isValidPropertyName(String name) {
// allow JMSX extensions or non JMS properties
return name.startsWith("JMSX") || !name.startsWith("JMS");
}
}

View File

@ -0,0 +1,3 @@
With a small amount of work to the controller, we should be able to delete these classes and instead
just expose the methods of the facades directly

View File

@ -0,0 +1,180 @@
/**
*
* Copyright 2005-2006 The Apache Software Foundation
*
* Licensed 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 org.springframework.web.bind.ServletRequestDataBinder;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import java.io.IOException;
import java.util.AbstractMap;
import java.util.Collections;
import java.util.Map;
import java.util.Set;
/**
* Exposes Spring ApplicationContexts to JSP EL and other view technologies.
* Currently a variable is placed in application scope (by default called
* 'applicationContext') so that POJOs can be pulled out of Spring in a JSP page
* to render things using EL expressions. <br/>
*
* e.g. ${applicationContext.cheese} would access the cheese POJO. Or
* ${applicationContext.cheese.name} would access the name property of the
* cheese POJO. <br/>
*
* You can then use JSTL to work with these POJOs such as &lt;c.set var="myfoo"
* value="${applicationContext.foo}"/&gt; <br/>
*
* In addition to applicationContext a 'requestContext' variable is created
* which will automatically bind any request parameters to the POJOs extracted
* from the applicationContext - which is ideal for POJOs which implement
* queries in view technologies.
*
* @version $Revision$
*/
public class ApplicationContextFilter implements Filter {
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);
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
// lets register a requestContext in the requestScope
Map requestContextWrapper = createRequestContextWrapper(request);
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) {
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;
}
/**
* Creates a wrapper around the request context (e.g. to allow POJOs to be
* auto-injected from request parameter values etc) so that it can be
* accessed easily from inside JSP EL (or other expression languages in
* other view technologies).
*/
protected Map createRequestContextWrapper(final ServletRequest request) {
final WebApplicationContext context = WebApplicationContextUtils.getWebApplicationContext(servletContext);
Map wrapper = new AbstractMap() {
public WebApplicationContext getContext() {
return context;
}
public Object get(Object key) {
if (key == null) {
return null;
}
return bindRequestBean(context.getBean(key.toString()), request);
}
public Set entrySet() {
return Collections.EMPTY_SET;
}
};
return wrapper;
}
/**
* Binds properties from the request parameters to the given POJO which is
* useful for POJOs which are configurable via request parameters such as
* for query/view POJOs
*/
protected Object bindRequestBean(Object bean, ServletRequest request) {
ServletRequestDataBinder binder = new ServletRequestDataBinder(bean, null);
binder.bind(request);
return bean;
}
}

View File

@ -0,0 +1,44 @@
/**
*
* Copyright 2005-2006 The Apache Software Foundation
*
* Licensed 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 org.springframework.web.bind.ServletRequestDataBinder;
import org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping;
import javax.servlet.http.HttpServletRequest;
/**
*
* @version $Revision$
*/
public class BindingBeanNameUrlHandlerMapping extends BeanNameUrlHandlerMapping {
protected Object getHandlerInternal(HttpServletRequest request) throws Exception {
Object object = super.getHandlerInternal(request);
if (object instanceof String) {
String handlerName = (String) object;
object = getApplicationContext().getBean(handlerName);
}
ServletRequestDataBinder binder = new ServletRequestDataBinder(object, null);
binder.bind(request);
System.out.println("Bound POJO is now: " + object);
return object;
}
}

View File

@ -0,0 +1,20 @@
#
# The logging properties used during tests..
#
log4j.rootLogger=INFO, stdout
log4j.logger.org.apache.activemq.spring=WARN
log4j.logger.org.springframework=warn
# CONSOLE appender not used by default
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d [%-15.15t] %-5p %-30.30c{1} - %m%n
# File appender
log4j.appender.out=org.apache.log4j.FileAppender
log4j.appender.out.layout=org.apache.log4j.PatternLayout
log4j.appender.out.layout.ConversionPattern=%d [%-15.15t] %-5p %-30.30c{1} - %m%n
log4j.appender.out.file=activemq-console.log
log4j.appender.out.append=true

View File

@ -0,0 +1 @@
classes

View File

@ -0,0 +1,99 @@
<!-- START SNIPPET: xbean -->
<beans xmlns="http://activemq.org/config/1.0">
<broker useJmx="true">
<!-- Use the following to set the broker memory limit (in bytes)
<memoryManager>
<usageManager id="memory-manager" limit="1048576"/>
</memoryManager>
-->
<!-- Use the following to configure how ActiveMQ is exposed in JMX
<managementContext>
<managementContext connectorPort="1099" jmxDomainName="org.apache.activemq"/>
</managementContext>
-->
<!-- In ActiveMQ 4, you can setup destination policies -->
<destinationPolicy>
<policyMap><policyEntries>
<policyEntry topic="FOO.>">
<dispatchPolicy>
<strictOrderDispatchPolicy />
</dispatchPolicy>
<subscriptionRecoveryPolicy>
<lastImageSubscriptionRecoveryPolicy />
</subscriptionRecoveryPolicy>
</policyEntry>
</policyEntries></policyMap>
</destinationPolicy>
<!--
<managementContext>
<managementContext findTigerMbeanServer="true"/>
</managementContext>
-->
<persistenceAdapter>
<journaledJDBC journalLogFiles="5" dataDirectory="activemq-data"/>
<!-- To use a different datasource, use th following syntax : -->
<!--
<journaledJDBC journalLogFiles="5" dataDirectory="activemq-data" dataSource="#postgres-ds"/>
-->
</persistenceAdapter>
<transportConnectors>
<transportConnector name="default" uri="tcp://localhost:61616" discoveryUri="multicast://default"/>
<transportConnector name="stomp" uri="stomp://localhost:61613"/>
</transportConnectors>
<networkConnectors>
<!-- by default just auto discover the other brokers -->
<networkConnector name="default" uri="multicast://default"/>
<!--
<networkConnector name="host1 and host2" uri="static://(tcp://host1:61616,tcp://host2:61616)" failover="true"/>
-->
</networkConnectors>
</broker>
<!-- This xbean configuration file supports all the standard spring xml configuration options -->
<!-- Postgres DataSource Sample Setup -->
<!--
<bean id="postgres-ds" class="org.postgresql.ds.PGPoolingDataSource">
<property name="serverName" value="localhost"/>
<property name="databaseName" value="activemq"/>
<property name="portNumber" value="0"/>
<property name="user" value="activemq"/>
<property name="password" value="activemq"/>
<property name="dataSourceName" value="postgres"/>
<property name="initialConnections" value="1"/>
<property name="maxConnections" value="10"/>
</bean>
-->
<!-- MySql DataSource Sample Setup -->
<!--
<bean id="mysql-ds" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost/activemq?relaxAutoCommit=true"/>
<property name="username" value="activemq"/>
<property name="password" value="activemq"/>
<property name="poolPreparedStatements" value="true"/>
</bean>
-->
<!-- Embedded Derby DataSource Sample Setup -->
<!--
<bean id="derby-ds" class="org.apache.derby.jdbc.EmbeddedDataSource">
<property name="databaseName" value="derbydb"/>
<property name="createDatabase" value="create"/>
</bean>
-->
</beans>
<!-- END SNIPPET: xbean -->

View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<bean id="placeholderConfig" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer" />
<bean id="brokerService" class="org.apache.activemq.xbean.BrokerFactoryBean">
<property name="config" value="/WEB-INF/activemq.xml"/>
</bean>
<bean id="sessionPool" class="org.apache.activemq.web.SessionPool"/>
<bean id="brokerQuery" class="org.apache.activemq.web.BrokerFacade" autowire='constructor'/>
<bean id="queueBrowser" class="org.apache.activemq.web.QueueBrowseQuery" autowire='constructor' singleton="false"/>
</beans>

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<decorators defaultdir="/decorators">
<decorator name="main" page="main.jsp">
<pattern>/*</pattern>
</decorator>
<decorator name="panel" page="panel.jsp"/>
<decorator name="printable" page="printable.jsp"/>
</decorators>

View File

@ -0,0 +1,41 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<bean id="handlerMapping" class="org.apache.activemq.web.handler.BindingBeanNameUrlHandlerMapping" singleton="false">
<!--
<property name="uriToClassNames">
<props><prop key="/foo.action">org.apache.activemq.web.controller.Foo</prop></props>
</property>
-->
</bean>
<bean name="/createDestination.action" class="org.apache.activemq.web.controller.CreateDestination" autowire="constructor" singleton="false"/>
<bean name="/deleteDestination.action" class="org.apache.activemq.web.controller.DeleteDestination" autowire="constructor" singleton="false"/>
<bean name="/createSubscriber.action" class="org.apache.activemq.web.controller.CreateSubscriber" autowire="constructor" singleton="false"/>
<bean name="/deleteSubscriber.action" class="org.apache.activemq.web.controller.DeleteSubscriber" autowire="constructor" singleton="false"/>
<bean name="/sendMessage.action" class="org.apache.activemq.web.controller.SendMessage" autowire="constructor" singleton="false"/>
<!--
- This bean resolves specific types of exception to corresponding error views.
- The default behaviour of DispatcherServlet is to propagate all exceptions to the
- servlet container: This will happen here with all other types of exception.
-->
<bean id="exceptionResolver" class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<property name="exceptionMappings">
<props><!-- <prop key="org.springframework.dao.DataAccessException">dataAccessFailure</prop> --></props>
</property>
</bean>
<!--
- This bean resolves default view names for controllers that do not explicitly
- specify a view name in their return ModelAndView (see ClinicController).
- This translator takes the request URL and extracts a view name from it: e.g.
- "/welcome.html" -> "welcome", plus configured "View" suffix -> "welcomeView".
-->
<!--
<bean id="viewNameTranslator" class="org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator">
<property name="suffix" value="View"/>
</bean>
-->
</beans>

View File

@ -0,0 +1,4 @@
<%@ taglib prefix="decorator" uri="http://www.opensymphony.com/sitemesh/decorator" %>
<%@ taglib prefix="form" tagdir="/WEB-INF/tags/form" %>
<%@ taglib prefix="jms" tagdir="/WEB-INF/tags/jms" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

View File

@ -0,0 +1,5 @@
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<%@ taglib prefix="display" uri="http://displaytag.sf.net" %>
<%@ taglib prefix="c" tagdir="/WEB-INF/tags/c" %>

View File

@ -0,0 +1,2 @@
<%@ attribute name="name" type="java.lang.String" required="true" %>
<input type="checkbox" name="${name}" value="true" ${param[name] ? 'checked' : ''}/>

View File

@ -0,0 +1,4 @@
<%@ attribute name="name" type="java.lang.String" required="true" %>
<%@ attribute name="value" type="java.lang.String" required="true" %>
<%@ attribute name="label" type="java.lang.String" required="true" %>
<option ${param[name] == value ? 'selected' : ''} value="${value}">${label}</option>

View File

@ -0,0 +1,12 @@
<%@ attribute name="name" type="java.lang.String" required="true" %>
<%@ attribute name="defaultValue" type="java.lang.String" required="false" %>
<%
String value = request.getParameter(name);
if (value == null || value.trim().length() == 0) {
value = defaultValue;
}
if (value == null) {
value = "";
}
%>
<input type="text" name="${name}" value="<%= value %>"/>

View File

@ -0,0 +1,2 @@
<%@ attribute name="name" type="java.lang.String" required="true" %>
<input type="text" name="${name}" value="${param[name]}" />

View File

@ -0,0 +1,18 @@
<%@ attribute name="var" type="java.lang.String" required="true" %>
<%@ attribute name="queueBrowser" type="javax.jms.QueueBrowser" required="true" %>
<%@ tag import="java.util.Enumeration" %>
<%@ tag import="javax.jms.Message" %>
<%
Enumeration iter = queueBrowser.getEnumeration();
while (iter.hasMoreElements()) {
Message message = (Message) iter.nextElement();
if (message != null) {
request.setAttribute(var, message);
%>
<jsp:doBody/>
<%
}
}
%>

View File

@ -0,0 +1,12 @@
<%@ attribute name="message" type="javax.jms.Message" required="true" %>
<%
System.out.println("Got message: " + message);
if (message != null) {
if (message.getJMSDeliveryMode() == javax.jms.DeliveryMode.PERSISTENT) {
out.println("Persistent");
}
else {
out.println("Non Persistent");
}
}
%>

View File

@ -0,0 +1,122 @@
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
version="2.4">
<description>
ActiveMQ Console
</description>
<display-name>ActiveMQ Console</display-name>
<!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
<!-- Configuration of the SiteMesh Filter. -->
<!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
<filter>
<filter-name>sitemesh</filter-name>
<filter-class>com.opensymphony.module.sitemesh.filter.PageFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>sitemesh</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
<!-- Expose Spring POJOs to JSP . -->
<!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
<filter>
<filter-name>spring</filter-name>
<filter-class>org.apache.activemq.web.filter.ApplicationContextFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>spring</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
<!-- ActiveMQ servlets -->
<!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
<!-- the subscription REST servlet -->
<servlet>
<servlet-name>AjaxServlet</servlet-name>
<servlet-class>org.apache.activemq.web.AjaxServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>AjaxServlet</servlet-name>
<url-pattern>/ajax/*</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>SendServlet</servlet-name>
<servlet-class>org.apache.activemq.web.MessageServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>SendServlet</servlet-name>
<url-pattern>/send/*</url-pattern>
</servlet-mapping>
<!-- the queue browse servlet -->
<servlet>
<servlet-name>QueueBrowseServlet</servlet-name>
<servlet-class>org.apache.activemq.web.QueueBrowseServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>QueueBrowseServlet</servlet-name>
<url-pattern>/queueBrowse/*</url-pattern>
</servlet-mapping>
<!-- track the session usage for web JMS clients -->
<filter>
<filter-name>session</filter-name>
<filter-class>org.apache.activemq.web.SessionFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>session</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
<!-- Spring listener. -->
<!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
<!-- Configuration of the Spring MVC dispatcher -->
<!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>2</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>*.action</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
<!-- Factor out common headers in JSP pages -->
<!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
<jsp-config>
<jsp-property-group>
<url-pattern>*.jsp</url-pattern>
<include-prelude>/WEB-INF/jspf/headertags.jspf</include-prelude>
</jsp-property-group>
</jsp-config>
</web-app>

View File

@ -0,0 +1,51 @@
<html>
<head>
<title>Browse ${requestContext.queueBrowser.JMSDestination}</title>
</head>
<body>
<h2>Browse ${requestContext.queueBrowser.JMSDestination}</h2>
<table id="messages" class="sortable autostripe">
<thead>
<tr>
<th>Message ID</th>
<th>Correlation ID</th>
<th>Persistence</th>
<th>Priority</th>
<th>Redelivered</th>
<th>Reply To</th>
<th>Timestamp</th>
<th>Type</th>
<th>Operations</th>
</tr>
</thead>
<tbody>
<%--
<c:forEach items="${requestContext.queueBrowser.browser.enumeration}" var="row">
---%>
<jms:forEachMessage queueBrowser="${requestContext.queueBrowser.browser}" var="row">
<tr>
<td><a href="message.jsp?id=${row.JMSMessageID}" title="${row.JMSDestination}">${row.JMSMessageID}</a></td>
<td>${row.JMSCorrelationID}</td>
<td><jms:persistent message="${row}"/></td>
<td>${row.JMSPriority}</td>
<td>${row.JMSRedelivered}</td>
<td>${row.JMSReplyTo}</td>
<td>${row.JMSTimestamp}</td>
<td>${row.JMSType}</td>
<td>
<a href="deleteDestination.action?destination=${row.JMSMessageID}">Delete</a>
</td>
</tr>
</jms:forEachMessage>
<%--
</c:forEach>
--%>
</tbody>
</table>
</body>
</html>

View File

@ -0,0 +1,65 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title><decorator:title default="ActiveMQ Console" /></title>
<style type="text/css" media="screen">
@import url(<c:url value="/styles/tools.css"/>);
@import url(<c:url value="/styles/forms.css"/>);
@import url(<c:url value="/styles/layout-navtop-subright.css"/>);
@import url(<c:url value="/styles/layout.css"/>);
@import url(<c:url value="/styles/tools.css"/>);
@import url(<c:url value="/styles/sorttable.css"/>);
@import url(<c:url value="/styles/deliciouslyblue.css"/>);
</style>
<script type='text/javascript' src='<c:url value="/js/common.js"/>'/>
<script type='text/javascript' src='<c:url value="/js/css.js"/>'/>
<script type='text/javascript' src='<c:url value="/js/standardista-table-sorting.js"/>'/>
<decorator:head />
</head>
<body id="page-home">
<div id="page">
<div id="header" class="clearfix">
<!--
<form name="form1" id="form1" method="post" action="">
<input type="text" name="textfield" value="Search For..." />
<input class=" button" type="submit" name="Submit" value="GO" />
</form>
-->
<h1>ActiveMQ Console</h1>
</div>
<div id="content" class="clearfix">
<div id="main">
<decorator:body />
</div>
<div id="nav">
<ul>
<li><a href="<c:url value='/index.jsp'/>" title="Home<"><span>Home</span></a></li>
<li><a href="<c:url value='/queues.jsp'/>" title="Queues"><span>Queues</span></a></li>
<li><a href="<c:url value='/topics.jsp'/>" title="Topics"><span>Topics</span></a></li>
<li><a href="<c:url value='/subscribers.jsp'/>" title="Subscribers"><span>Subscribers</span></a></li>
<li><a href="<c:url value='/send.jsp'/>" title="Send"><span>Send</span></a></li>
</ul>
</div>
<div id="footer">
<p>
Copyright 2005-2006 The Apache Software Foundation
</p>
<p><small>(<a href="?printable=true">printable version</a>)</small></p>
</div>
</div>
</body>
</html>

View File

@ -0,0 +1,16 @@
<%@ taglib uri="http://www.opensymphony.com/sitemesh/decorator" prefix="decorator" %>
<p>
<table border="0" cellpadding="0" cellspacing="0">
<tr>
<th class="panelTitle">
<decorator:title default="Unknown panel" />
</th>
</tr>
<tr>
<td class="panelBody">
<decorator:body />
</td>
</tr>
</table>
</p>

View File

@ -0,0 +1,15 @@
<%@ taglib uri="http://www.opensymphony.com/sitemesh/decorator" prefix="decorator" %>
<html>
<head>
<title><decorator:title default="Welcome!" /></title>
<decorator:head />
</head>
<body onload="window.print();">
Printed on <%=new java.util.Date()%>.<br/>
<hr noshade="noshade" size="1"/>
<br/>
<decorator:body />
</body>
</html>

View File

@ -0,0 +1,51 @@
<html>
<head>
<title>Browse ${requestContext.queueBrowser.JMSDestination}</title>
</head>
<body>
<h2>Browse ${requestContext.queueBrowser.JMSDestination}</h2>
<table id="messages" class="sortable autostripe">
<thead>
<tr>
<th>Message ID</th>
<th>Correlation ID</th>
<th>Persistence</th>
<th>Priority</th>
<th>Redelivered</th>
<th>Reply To</th>
<th>Timestamp</th>
<th>Type</th>
<th>Operations</th>
</tr>
</thead>
<tbody>
<%--
<c:forEach items="${requestContext.queueBrowser.browser.enumeration}" var="row">
---%>
<jms:forEachMessage queueBrowser="${requestContext.queueBrowser.browser}" var="row">
<tr>
<td><a href="message.jsp?id=${row.JMSMessageID}" title="${row.JMSDestination}">${row.JMSMessageID}</a></td>
<td>${row.JMSCorrelationID}</td>
<td><jms:persistent message="${row}"/></td>
<td>${row.JMSPriority}</td>
<td>${row.JMSRedelivered}</td>
<td>${row.JMSReplyTo}</td>
<td>${row.JMSTimestamp}</td>
<td>${row.JMSType}</td>
<td>
<a href="deleteDestination.action?destination=${row.JMSMessageID}">Delete</a>
</td>
</tr>
</jms:forEachMessage>
<%--
</c:forEach>
--%>
</tbody>
</table>
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 875 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 429 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 637 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@ -0,0 +1,18 @@
<html>
<head>
<title>ActiveMQ Console</title>
</head>
<body>
<h2>Welcome!</h2>
<p>
Welcome to the ActiveMQ Console
</p>
<p>
You can find more information about ActiveMQ on the <a href="http://incubator.apache.org/activemq/">Apache ActiveMQ Site</a>
</p>
</body>
</html>

View File

@ -0,0 +1,105 @@
/**
* addEvent written by Dean Edwards, 2005
* with input from Tino Zijdel
*
* http://dean.edwards.name/weblog/2005/10/add-event/
**/
function addEvent(element, type, handler) {
// assign each event handler a unique ID
if (!handler.$$guid) handler.$$guid = addEvent.guid++;
// create a hash table of event types for the element
if (!element.events) element.events = {};
// create a hash table of event handlers for each element/event pair
var handlers = element.events[type];
if (!handlers) {
handlers = element.events[type] = {};
// store the existing event handler (if there is one)
if (element["on" + type]) {
handlers[0] = element["on" + type];
}
}
// store the event handler in the hash table
handlers[handler.$$guid] = handler;
// assign a global event handler to do all the work
element["on" + type] = handleEvent;
};
// a counter used to create unique IDs
addEvent.guid = 1;
function removeEvent(element, type, handler) {
// delete the event handler from the hash table
if (element.events && element.events[type]) {
delete element.events[type][handler.$$guid];
}
};
function handleEvent(event) {
var returnValue = true;
// grab the event object (IE uses a global event object)
event = event || fixEvent(window.event);
// get a reference to the hash table of event handlers
var handlers = this.events[event.type];
// execute each event handler
for (var i in handlers) {
this.$$handleEvent = handlers[i];
if (this.$$handleEvent(event) === false) {
returnValue = false;
}
}
return returnValue;
};
function fixEvent(event) {
// add W3C standard event methods
event.preventDefault = fixEvent.preventDefault;
event.stopPropagation = fixEvent.stopPropagation;
return event;
};
fixEvent.preventDefault = function() {
this.returnValue = false;
};
fixEvent.stopPropagation = function() {
this.cancelBubble = true;
};
// end from Dean Edwards
/**
* Creates an Element for insertion into the DOM tree.
* From http://simon.incutio.com/archive/2003/06/15/javascriptWithXML
*
* @param element the element type to be created.
* e.g. ul (no angle brackets)
**/
function createElement(element) {
if (typeof document.createElementNS != 'undefined') {
return document.createElementNS('http://www.w3.org/1999/xhtml', element);
}
if (typeof document.createElement != 'undefined') {
return document.createElement(element);
}
return false;
}
/**
* "targ" is the element which caused this function to be called
* from http://www.quirksmode.org/js/events_properties.html
**/
function getEventTarget(e) {
var targ;
if (!e) {
e = window.event;
}
if (e.target) {
targ = e.target;
} else if (e.srcElement) {
targ = e.srcElement;
}
if (targ.nodeType == 3) { // defeat Safari bug
targ = targ.parentNode;
}
return targ;
}

View File

@ -0,0 +1,145 @@
/**
* Written by Neil Crosby.
* http://www.workingwith.me.uk/
*
* Use this wherever you want, but please keep this comment at the top of this file.
*
* Copyright (c) 2006 Neil Crosby
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
**/
var css = {
/**
* Returns an array containing references to all elements
* of a given tag type within a certain node which have a given class
*
* @param node the node to start from
* (e.g. document,
* getElementById('whateverStartpointYouWant')
* )
* @param searchClass the class we're wanting
* (e.g. 'some_class')
* @param tag the tag that the found elements are allowed to be
* (e.g. '*', 'div', 'li')
**/
getElementsByClass : function(node, searchClass, tag) {
var classElements = new Array();
var els = node.getElementsByTagName(tag);
var elsLen = els.length;
var pattern = new RegExp("(^|\\s)"+searchClass+"(\\s|$)");
for (var i = 0, j = 0; i < elsLen; i++) {
if (this.elementHasClass(els[i], searchClass) ) {
classElements[j] = els[i];
j++;
}
}
return classElements;
},
/**
* PRIVATE. Returns an array containing all the classes applied to this
* element.
*
* Used internally by elementHasClass(), addClassToElement() and
* removeClassFromElement().
**/
privateGetClassArray: function(el) {
return el.className.split(' ');
},
/**
* PRIVATE. Creates a string from an array of class names which can be used
* by the className function.
*
* Used internally by addClassToElement().
**/
privateCreateClassString: function(classArray) {
return classArray.join(' ');
},
/**
* Returns true if the given element has been assigned the given class.
**/
elementHasClass: function(el, classString) {
if (!el) {
return false;
}
var regex = new RegExp('\\b'+classString+'\\b');
if (el.className.match(regex)) {
return true;
}
return false;
},
/**
* Adds classString to the classes assigned to the element with id equal to
* idString.
**/
addClassToId: function(idString, classString) {
this.addClassToElement(document.getElementById(idString), classString);
},
/**
* Adds classString to the classes assigned to the given element.
* If the element already has the class which was to be added, then
* it is not added again.
**/
addClassToElement: function(el, classString) {
var classArray = this.privateGetClassArray(el);
if (this.elementHasClass(el, classString)) {
return; // already has element so don't need to add it
}
classArray.push(classString);
el.className = this.privateCreateClassString(classArray);
},
/**
* Removes the given classString from the list of classes assigned to the
* element with id equal to idString
**/
removeClassFromId: function(idString, classString) {
this.removeClassFromElement(document.getElementById(idString), classString);
},
/**
* Removes the given classString from the list of classes assigned to the
* given element. If the element has the same class assigned to it twice,
* then only the first instance of that class is removed.
**/
removeClassFromElement: function(el, classString) {
var classArray = this.privateGetClassArray(el);
for (x in classArray) {
if (classString == classArray[x]) {
classArray[x] = '';
break;
}
}
el.className = this.privateCreateClassString(classArray);
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,185 @@
addEvent(window, "load", sortables_init);
var SORT_COLUMN_INDEX;
function sortables_init() {
// Find all tables with class sortable and make them sortable
if (!document.getElementsByTagName) return;
tbls = document.getElementsByTagName("table");
for (ti=0;ti<tbls.length;ti++) {
thisTbl = tbls[ti];
if (((' '+thisTbl.className+' ').indexOf("sortable") != -1) && (thisTbl.id)) {
//initTable(thisTbl.id);
ts_makeSortable(thisTbl);
}
}
}
function ts_makeSortable(table) {
if (table.rows && table.rows.length > 0) {
var firstRow = table.rows[0];
}
if (!firstRow) return;
// We have a first row: assume it's the header, and make its contents clickable links
for (var i=0;i<firstRow.cells.length;i++) {
var cell = firstRow.cells[i];
var txt = ts_getInnerText(cell);
cell.innerHTML = '<a href="#" class="sortheader" '+
'onclick="ts_resortTable(this, '+i+');return false;">' +
txt+'<span class="sortarrow">&nbsp;&nbsp;&nbsp;</span></a>';
}
}
function ts_getInnerText(el) {
if (typeof el == "string") return el;
if (typeof el == "undefined") { return el };
if (el.innerText) return el.innerText; //Not needed but it is faster
var str = "";
var cs = el.childNodes;
var l = cs.length;
for (var i = 0; i < l; i++) {
switch (cs[i].nodeType) {
case 1: //ELEMENT_NODE
str += ts_getInnerText(cs[i]);
break;
case 3: //TEXT_NODE
str += cs[i].nodeValue;
break;
}
}
return str;
}
function ts_resortTable(lnk,clid) {
// get the span
var span;
for (var ci=0;ci<lnk.childNodes.length;ci++) {
if (lnk.childNodes[ci].tagName && lnk.childNodes[ci].tagName.toLowerCase() == 'span') span = lnk.childNodes[ci];
}
var spantext = ts_getInnerText(span);
var td = lnk.parentNode;
var column = clid || td.cellIndex;
var table = getParent(td,'TABLE');
// Work out a type for the column
if (table.rows.length <= 1) return;
var itm = ts_getInnerText(table.rows[1].cells[column]);
sortfn = ts_sort_caseinsensitive;
if (itm.match(/^\d\d[\/-]\d\d[\/-]\d\d\d\d$/)) sortfn = ts_sort_date;
if (itm.match(/^\d\d[\/-]\d\d[\/-]\d\d$/)) sortfn = ts_sort_date;
if (itm.match(/^[£$]/)) sortfn = ts_sort_currency;
if (itm.match(/^[\d\.]+$/)) sortfn = ts_sort_numeric;
SORT_COLUMN_INDEX = column;
var firstRow = new Array();
var newRows = new Array();
for (i=0;i<table.rows[0].length;i++) { firstRow[i] = table.rows[0][i]; }
for (j=1;j<table.rows.length;j++) { newRows[j-1] = table.rows[j]; }
newRows.sort(sortfn);
if (span.getAttribute("sortdir") == 'down') {
ARROW = '&nbsp;&nbsp;&uarr;';
newRows.reverse();
span.setAttribute('sortdir','up');
} else {
ARROW = '&nbsp;&nbsp;&darr;';
span.setAttribute('sortdir','down');
}
// We appendChild rows that already exist to the tbody, so it moves them rather than creating new ones
// don't do sortbottom rows
for (i=0;i<newRows.length;i++) { if (!newRows[i].className || (newRows[i].className && (newRows[i].className.indexOf('sortbottom') == -1))) table.tBodies[0].appendChild(newRows[i]);}
// do sortbottom rows only
for (i=0;i<newRows.length;i++) { if (newRows[i].className && (newRows[i].className.indexOf('sortbottom') != -1)) table.tBodies[0].appendChild(newRows[i]);}
// Delete any other arrows there may be showing
var allspans = document.getElementsByTagName("span");
for (var ci=0;ci<allspans.length;ci++) {
if (allspans[ci].className == 'sortarrow') {
if (getParent(allspans[ci],"table") == getParent(lnk,"table")) { // in the same table as us?
allspans[ci].innerHTML = '&nbsp;&nbsp;&nbsp;';
}
}
}
span.innerHTML = ARROW;
}
function getParent(el, pTagName) {
if (el == null) return null;
else if (el.nodeType == 1 && el.tagName.toLowerCase() == pTagName.toLowerCase()) // Gecko bug, supposed to be uppercase
return el;
else
return getParent(el.parentNode, pTagName);
}
function ts_sort_date(a,b) {
// y2k notes: two digit years less than 50 are treated as 20XX, greater than 50 are treated as 19XX
aa = ts_getInnerText(a.cells[SORT_COLUMN_INDEX]);
bb = ts_getInnerText(b.cells[SORT_COLUMN_INDEX]);
if (aa.length == 10) {
dt1 = aa.substr(6,4)+aa.substr(3,2)+aa.substr(0,2);
} else {
yr = aa.substr(6,2);
if (parseInt(yr) < 50) { yr = '20'+yr; } else { yr = '19'+yr; }
dt1 = yr+aa.substr(3,2)+aa.substr(0,2);
}
if (bb.length == 10) {
dt2 = bb.substr(6,4)+bb.substr(3,2)+bb.substr(0,2);
} else {
yr = bb.substr(6,2);
if (parseInt(yr) < 50) { yr = '20'+yr; } else { yr = '19'+yr; }
dt2 = yr+bb.substr(3,2)+bb.substr(0,2);
}
if (dt1==dt2) return 0;
if (dt1<dt2) return -1;
return 1;
}
function ts_sort_currency(a,b) {
aa = ts_getInnerText(a.cells[SORT_COLUMN_INDEX]).replace(/[^0-9.]/g,'');
bb = ts_getInnerText(b.cells[SORT_COLUMN_INDEX]).replace(/[^0-9.]/g,'');
return parseFloat(aa) - parseFloat(bb);
}
function ts_sort_numeric(a,b) {
aa = parseFloat(ts_getInnerText(a.cells[SORT_COLUMN_INDEX]));
if (isNaN(aa)) aa = 0;
bb = parseFloat(ts_getInnerText(b.cells[SORT_COLUMN_INDEX]));
if (isNaN(bb)) bb = 0;
return aa-bb;
}
function ts_sort_caseinsensitive(a,b) {
aa = ts_getInnerText(a.cells[SORT_COLUMN_INDEX]).toLowerCase();
bb = ts_getInnerText(b.cells[SORT_COLUMN_INDEX]).toLowerCase();
if (aa==bb) return 0;
if (aa<bb) return -1;
return 1;
}
function ts_sort_default(a,b) {
aa = ts_getInnerText(a.cells[SORT_COLUMN_INDEX]);
bb = ts_getInnerText(b.cells[SORT_COLUMN_INDEX]);
if (aa==bb) return 0;
if (aa<bb) return -1;
return 1;
}
function addEvent(elm, evType, fn, useCapture)
// addEvent and removeEvent
// cross-browser event handling for IE5+, NS6 and Mozilla
// By Scott Andrew
{
if (elm.addEventListener){
elm.addEventListener(evType, fn, useCapture);
return true;
} else if (elm.attachEvent){
var r = elm.attachEvent("on"+evType, fn);
return r;
} else {
alert("Handler could not be removed");
}
}

View File

@ -0,0 +1,428 @@
/**
* Written by Neil Crosby.
* http://www.workingwith.me.uk/articles/scripting/standardista_table_sorting
*
* This module is based on Stuart Langridge's "sorttable" code. Specifically,
* the determineSortFunction, sortCaseInsensitive, sortDate, sortNumeric, and
* sortCurrency functions are heavily based on his code. This module would not
* have been possible without Stuart's earlier outstanding work.
*
* Use this wherever you want, but please keep this comment at the top of this file.
*
* Copyright (c) 2006 Neil Crosby
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
**/
var standardistaTableSorting = {
that: false,
isOdd: false,
sortColumnIndex : -1,
lastAssignedId : 0,
newRows: -1,
lastSortedTable: -1,
/**
* Initialises the Standardista Table Sorting module
**/
init : function() {
// first, check whether this web browser is capable of running this script
if (!document.getElementsByTagName) {
return;
}
this.that = this;
this.run();
},
/**
* Runs over each table in the document, making it sortable if it has a class
* assigned named "sortable" and an id assigned.
**/
run : function() {
var tables = document.getElementsByTagName("table");
for (var i=0; i < tables.length; i++) {
var thisTable = tables[i];
if (css.elementHasClass(thisTable, 'sortable')) {
this.makeSortable(thisTable);
}
}
},
/**
* Makes the given table sortable.
**/
makeSortable : function(table) {
// first, check if the table has an id. if it doesn't, give it one
if (!table.id) {
table.id = 'sortableTable'+this.lastAssignedId++;
}
// if this table does not have a thead, we don't want to know about it
if (!table.tHead || !table.tHead.rows || 0 == table.tHead.rows.length) {
return;
}
// we'll assume that the last row of headings in the thead is the row that
// wants to become clickable
var row = table.tHead.rows[table.tHead.rows.length - 1];
for (var i=0; i < row.cells.length; i++) {
// create a link with an onClick event which will
// control the sorting of the table
var linkEl = createElement('a');
linkEl.href = '#';
linkEl.onclick = this.headingClicked;
linkEl.setAttribute('columnId', i);
linkEl.title = 'Click to sort';
// move the current contents of the cell that we're
// hyperlinking into the hyperlink
var innerEls = row.cells[i].childNodes;
for (var j = 0; j < innerEls.length; j++) {
linkEl.appendChild(innerEls[j]);
}
// and finally add the new link back into the cell
row.cells[i].appendChild(linkEl);
var spanEl = createElement('span');
spanEl.className = 'tableSortArrow';
spanEl.appendChild(document.createTextNode('\u00A0\u00A0'));
row.cells[i].appendChild(spanEl);
}
if (css.elementHasClass(table, 'autostripe')) {
this.isOdd = false;
var rows = table.tBodies[0].rows;
// We appendChild rows that already exist to the tbody, so it moves them rather than creating new ones
for (var i=0;i<rows.length;i++) {
this.doStripe(rows[i]);
}
}
},
headingClicked: function(e) {
var that = standardistaTableSorting.that;
// linkEl is the hyperlink that was clicked on which caused
// this method to be called
var linkEl = getEventTarget(e);
// directly outside it is a td, tr, thead and table
var td = linkEl.parentNode;
var tr = td.parentNode;
var thead = tr.parentNode;
var table = thead.parentNode;
// if the table we're looking at doesn't have any rows
// (or only has one) then there's no point trying to sort it
if (!table.tBodies || table.tBodies[0].rows.length <= 1) {
return false;
}
// the column we want is indicated by td.cellIndex
var column = linkEl.getAttribute('columnId') || td.cellIndex;
//var column = td.cellIndex;
// find out what the current sort order of this column is
var arrows = css.getElementsByClass(td, 'tableSortArrow', 'span');
var previousSortOrder = '';
if (arrows.length > 0) {
previousSortOrder = arrows[0].getAttribute('sortOrder');
}
// work out how we want to sort this column using the data in the first cell
// but just getting the first cell is no good if it contains no data
// so if the first cell just contains white space then we need to track
// down until we find a cell which does contain some actual data
var itm = ''
var rowNum = 0;
while ('' == itm && rowNum < table.tBodies[0].rows.length) {
itm = that.getInnerText(table.tBodies[0].rows[rowNum].cells[column]);
rowNum++;
}
var sortfn = that.determineSortFunction(itm);
// if the last column that was sorted was this one, then all we need to
// do is reverse the sorting on this column
if (table.id == that.lastSortedTable && column == that.sortColumnIndex) {
newRows = that.newRows;
newRows.reverse();
// otherwise, we have to do the full sort
} else {
that.sortColumnIndex = column;
var newRows = new Array();
for (var j = 0; j < table.tBodies[0].rows.length; j++) {
newRows[j] = table.tBodies[0].rows[j];
}
newRows.sort(sortfn);
}
that.moveRows(table, newRows);
that.newRows = newRows;
that.lastSortedTable = table.id;
// now, give the user some feedback about which way the column is sorted
// first, get rid of any arrows in any heading cells
var arrows = css.getElementsByClass(tr, 'tableSortArrow', 'span');
for (var j = 0; j < arrows.length; j++) {
var arrowParent = arrows[j].parentNode;
arrowParent.removeChild(arrows[j]);
if (arrowParent != td) {
spanEl = createElement('span');
spanEl.className = 'tableSortArrow';
spanEl.appendChild(document.createTextNode('\u00A0\u00A0'));
arrowParent.appendChild(spanEl);
}
}
// now, add back in some feedback
var spanEl = createElement('span');
spanEl.className = 'tableSortArrow';
if (null == previousSortOrder || '' == previousSortOrder || 'DESC' == previousSortOrder) {
spanEl.appendChild(document.createTextNode(' \u2191'));
spanEl.setAttribute('sortOrder', 'ASC');
} else {
spanEl.appendChild(document.createTextNode(' \u2193'));
spanEl.setAttribute('sortOrder', 'DESC');
}
td.appendChild(spanEl);
return false;
},
getInnerText : function(el) {
if ('string' == typeof el || 'undefined' == typeof el) {
return el;
}
if (el.innerText) {
return el.innerText; // Not needed but it is faster
}
var str = el.getAttribute('standardistaTableSortingInnerText');
if (null != str && '' != str) {
return str;
}
str = '';
var cs = el.childNodes;
var l = cs.length;
for (var i = 0; i < l; i++) {
// 'if' is considerably quicker than a 'switch' statement,
// in Internet Explorer which translates up to a good time
// reduction since this is a very often called recursive function
if (1 == cs[i].nodeType) { // ELEMENT NODE
str += this.getInnerText(cs[i]);
break;
} else if (3 == cs[i].nodeType) { //TEXT_NODE
str += cs[i].nodeValue;
break;
}
}
// set the innertext for this element directly on the element
// so that it can be retrieved early next time the innertext
// is requested
el.setAttribute('standardistaTableSortingInnerText', str);
return str;
},
determineSortFunction : function(itm) {
var sortfn = this.sortCaseInsensitive;
if (itm.match(/^\d\d[\/-]\d\d[\/-]\d\d\d\d$/)) {
sortfn = this.sortDate;
}
if (itm.match(/^\d\d[\/-]\d\d[\/-]\d\d$/)) {
sortfn = this.sortDate;
}
if (itm.match(/^[£$]/)) {
sortfn = this.sortCurrency;
}
if (itm.match(/^\d?\.?\d+$/)) {
sortfn = this.sortNumeric;
}
if (itm.match(/^[+-]?\d*\.?\d+([eE]-?\d+)?$/)) {
sortfn = this.sortNumeric;
}
if (itm.match(/^([01]?\d\d?|2[0-4]\d|25[0-5])\.([01]?\d\d?|2[0-4]\d|25[0-5])\.([01]?\d\d?|2[0-4]\d|25[0-5])\.([01]?\d\d?|2[0-4]\d|25[0-5])$/)) {
sortfn = this.sortIP;
}
return sortfn;
},
sortCaseInsensitive : function(a, b) {
var that = standardistaTableSorting.that;
var aa = that.getInnerText(a.cells[that.sortColumnIndex]).toLowerCase();
var bb = that.getInnerText(b.cells[that.sortColumnIndex]).toLowerCase();
if (aa==bb) {
return 0;
} else if (aa<bb) {
return -1;
} else {
return 1;
}
},
sortDate : function(a,b) {
var that = standardistaTableSorting.that;
// y2k notes: two digit years less than 50 are treated as 20XX, greater than 50 are treated as 19XX
var aa = that.getInnerText(a.cells[that.sortColumnIndex]);
var bb = that.getInnerText(b.cells[that.sortColumnIndex]);
var dt1, dt2, yr = -1;
if (aa.length == 10) {
dt1 = aa.substr(6,4)+aa.substr(3,2)+aa.substr(0,2);
} else {
yr = aa.substr(6,2);
if (parseInt(yr) < 50) {
yr = '20'+yr;
} else {
yr = '19'+yr;
}
dt1 = yr+aa.substr(3,2)+aa.substr(0,2);
}
if (bb.length == 10) {
dt2 = bb.substr(6,4)+bb.substr(3,2)+bb.substr(0,2);
} else {
yr = bb.substr(6,2);
if (parseInt(yr) < 50) {
yr = '20'+yr;
} else {
yr = '19'+yr;
}
dt2 = yr+bb.substr(3,2)+bb.substr(0,2);
}
if (dt1==dt2) {
return 0;
} else if (dt1<dt2) {
return -1;
}
return 1;
},
sortCurrency : function(a,b) {
var that = standardistaTableSorting.that;
var aa = that.getInnerText(a.cells[that.sortColumnIndex]).replace(/[^0-9.]/g,'');
var bb = that.getInnerText(b.cells[that.sortColumnIndex]).replace(/[^0-9.]/g,'');
return parseFloat(aa) - parseFloat(bb);
},
sortNumeric : function(a,b) {
var that = standardistaTableSorting.that;
var aa = parseFloat(that.getInnerText(a.cells[that.sortColumnIndex]));
if (isNaN(aa)) {
aa = 0;
}
var bb = parseFloat(that.getInnerText(b.cells[that.sortColumnIndex]));
if (isNaN(bb)) {
bb = 0;
}
return aa-bb;
},
makeStandardIPAddress : function(val) {
var vals = val.split('.');
for (x in vals) {
val = vals[x];
while (3 > val.length) {
val = '0'+val;
}
vals[x] = val;
}
val = vals.join('.');
return val;
},
sortIP : function(a,b) {
var that = standardistaTableSorting.that;
var aa = that.makeStandardIPAddress(that.getInnerText(a.cells[that.sortColumnIndex]).toLowerCase());
var bb = that.makeStandardIPAddress(that.getInnerText(b.cells[that.sortColumnIndex]).toLowerCase());
if (aa==bb) {
return 0;
} else if (aa<bb) {
return -1;
} else {
return 1;
}
},
moveRows : function(table, newRows) {
this.isOdd = false;
// We appendChild rows that already exist to the tbody, so it moves them rather than creating new ones
for (var i=0;i<newRows.length;i++) {
var rowItem = newRows[i];
this.doStripe(rowItem);
table.tBodies[0].appendChild(rowItem);
}
},
doStripe : function(rowItem) {
if (this.isOdd) {
css.addClassToElement(rowItem, 'odd');
} else {
css.removeClassFromElement(rowItem, 'odd');
}
this.isOdd = !this.isOdd;
}
}
function standardistaTableSortingInit() {
standardistaTableSorting.init();
}
addEvent(window, 'load', standardistaTableSortingInit)

View File

@ -0,0 +1,59 @@
<html>
<head>
<title>Message ${requestContext.messageBrowser.id}</title>
</head>
<body>
<table id="message" class="sortable autostripe">
<thead>
<tr>
<th>
Message Details
</th>
</tr>
</thead>
<tbody>
<tr>
<td class="label">Message ID</td>
<td>${row.JMSMessageID</td>
</tr>
<tr>
<td class="label">Destination</td>
<td>${row.JMSDestination}</td>
</tr>
<tr>
<td class="label">Correlation ID</td>
<td>${row.JMSCorrelationID}</td>
</tr>
<tr>
<td class="label">Persistence</td>
<td><jms:persistent message="${row}"/></td>
</tr>
<tr>
<td class="label">Priority</td>
<td>${row.JMSPriority}</td>
</tr>
<tr>
<td class="label">Redelivered</td>
<td>${row.JMSRedelivered}</td>
</tr>
<tr>
<td class="label">Reply To</td>
<td>${row.JMSReplyTo}</td>
</tr>
<tr>
<td class="label">Timestamp</td>
<td>${row.JMSTimestamp}</td>
</tr>
<tr>
<td class="label">Type</td>
<td>${row.JMSType}</td>
</tr>
</tbody>
</table>
</body>
</html>

View File

@ -0,0 +1,61 @@
<html>
<head>
<title>Queues</title>
</head>
<body>
<div>
<form action="createDestination.action" method="get">
<input type="hidden" name="JMSDestinationType" value="queue"/>
<label name="destination">Queue Name</label>
<input type="text" name="JMSDestination" value=""/>
<input type="submit" value="Create"/>
</form>
</div>
<h2>Queues</h2>
<table id="queues" class="sortable autostripe">
<thead>
<tr>
<th>Name</th>
<th>Number Of Pending Messages</th>
<th>Number Of Consumers</th>
<th>Messages Sent</th>
<th>Messages Received</th>
<th>Views</th>
<th>Operations</th>
</tr>
</thead>
<tbody>
<c:forEach items="${requestContext.brokerQuery.queues}" var="row">
<tr>
<td><a href="browse.jsp?JMSDestination=${row.name}">${row.name}</a></td>
<td>${row.queueSize}</td>
<td>${row.consumerCount}</td>
<td>${row.enqueueCount}</td>
<td>${row.dequeueCount}</td>
<td>
<a href="browse.jsp?JMSDestination=${row.name}">Browse</a>
<%--
<a href="graph.jsp?JMSDestination=${row.name}">Graph</a>
--%>
<a href="queueBrowse/${row.name}?view=rss&feedType=atom_1.0" title="Atom 1.0"><img src="images/atombadge.png"/></a>
<a href="queueBrowse/${row.name}?view=rss&ffeedType=rss_2.0" title="RSS 2.0"><img src="images/rssbadge.gif"/></a>
</td>
<td>
<a href="send.jsp?JMSDestination=${row.name}&JMSDestinationType=queue">Send To</a>
<a href="purgeDestination.action?JMSDestination=${row.name}&JMSDestinationType=queue">Purge</a>
<a href="deleteDestination.action?JMSDestination=${row.name}&JMSDestinationType=queue">Delete</a>
</td>
</tr>
</c:forEach>
</tbody>
</table>
</body>
</html>

View File

@ -0,0 +1,128 @@
<html>
<head>
<title>Send Messages</title>
</head>
<body>
<h1>Send a JMS Message</h1>
<form action="sendMessage.action" method="post">
<table id="headers" class="autostripe">
<thead>
<tr>
<th colspan="4">Message Header</th>
</tr>
</thead>
<tbody>
<tr>
<td class="label">
<label for="JMSDestination">Destination</label>
</td>
<td>
<form:text name="JMSDestination"/>
</td>
<td class="label">
<label for="queue">Queue or Topic</label>
</td>
<td>
<select name="JMSDestinationType">
<form:option name="JMSDestinationType" value="queue" label="Queue"/>
<form:option name="JMSDestinationType" value="topic" label="Topic"/>
</select>
</td>
</tr>
<tr>
<td class="label">
<label for="JMSCorrelationID">Correlation ID</label>
</td>
<td>
<form:text name="JMSCorrelationID"/>
</td>
<td class="label">
<label for="JMSPersistent">Persistent Delivery</label>
</td>
<td>
<form:checkbox name="JMSPersistent"/>
</td>
</tr>
<tr>
<td class="label">
<label for="JMSReplyTo">Reply To</label>
</td>
<td>
<form:text name="JMSReplyTo"/>
</td>
<td class="label">
<label for="JMSPriority">Priority</label>
</td>
<td>
<form:text name="JMSPriority"/>
</td>
</tr>
<tr>
<td class="label">
<label for="JMSType">Type</label>
</td>
<td>
<form:text name="JMSType"/>
</td>
<td class="label">
<label for="JMSTimeToLive">Time to live</label>
</td>
<td>
<form:text name="JMSTimeToLive"/>
</td>
</tr>
<tr>
<td class="label">
<label for="JMSXGroupID">Message Group</label>
</td>
<td>
<form:text name="JMSXGroupID"/>
</td>
<td class="label">
<label for="JMSXGroupSeq">Message Group Sequence Number</label>
</td>
<td>
<form:text name="JMSXGroupSeq"/>
</td>
</tr>
<tr>
<td class="label">
<label for="JMSMessageCount">Number of messages to send</label>
</td>
<td>
<form:text name="JMSMessageCount" defaultValue="1"/>
</td>
<td class="label">
<label for="JMSMessageCountHeader">Header to store the counter</label>
</td>
<td>
<form:text name="JMSMessageCountHeader" defaultValue="JMSXMessageCounter"/>
</td>
</tr>
<tr>
<th colspan="4" class="label">
<label for="text">Message body</label>
</th>
</tr>
<tr>
<td colspan="4">
<textarea name="JMSText" rows="30" cols="80">Enter some text here for the message body...</textarea>
</td>
</tr>
<tr>
<td colspan="4" align="center">
<input type="submit" value="Send"/>
<input type="reset"/>
</td>
</tr>
</tbody>
</table>
</form>
</body>
</html>

View File

@ -0,0 +1,233 @@
/**************** body and tag styles ****************/
body {
margin-top: 0px;
margin-bottom: 30px;
}
div#page {
width: 750px;
margin: 0 auto;
font-family: Verdana, Arial, Helvetica, sans-serif;
font-size: 11px;
line-height: 1.6em;
color: #666666;
background-color: #FFFFFF;
padding-bottom: 10px;
border-bottom: 2px solid #2763A5;
}
div#content {
width: 100%;
margin: 0 auto;
font-family: Verdana, Arial, Helvetica, sans-serif;
font-size: 11px;
color: #666666;
background-color: #FFFFFF;
padding-top: 10px;
}
div#header h1 {
font-family: "Trebuchet MS", Arial, Helvetica, sans-serif;
font-weight: normal;
font-size: 32px;
color: #003366;
margin-bottom: 16px;
background-color: #FFFFFF;
}
div#header p {
margin-bottom: 20px;
}
div#main h1, div#main h2 {
color: #666666;
font-size: 16px;
font-family: Arial, Helvetica, sans-serif;
background-color: #FFFFFF;
font-weight: bold;
}
div#main h3 {
font-size: 14px;
}
a, a:visited {
color: #003366;
/*background-color: #FFFFFF; */
text-decoration: none;
font-weight: bold;
}
a:hover {
/*background-color: #FFFFFF; */
color: inherit;
font-weight: bold;
text-decoration: underline;
}
/**************** images styles ****************/
a img{
border: none;
}
img.left,img.center,img.right {
padding: 4px;
border: 1px solid #a0a0a0;
}
img.left {
float: left;
margin: 0 12px 5px 0;
}
img.center {
display: block;
margin: 0 auto 5px auto;
}
img.right {
float: right;
margin: 0 0 5px 12px;
}
/**************** form styles ****************/
.button, button {
padding: 2px;
background-color: #003366;
color: #FFFFFF;
border: 1px solid #2763A5;
font-size: 11px;
}
div#main form p {
border-bottom: 0px;
padding-bottom: 0px;
}
/**************** header styles ****************/
div#header {
width: 750px;
border: 0px;
padding-bottom: 18px;
padding-top: 16px;
}
div#header div#branding {
display: none;
}
div#header p {
margin-top: -20px;
margin-left: 30px;
color: #999999;
}
/**************** menu styles ****************/
div#nav {
float: left;
width: 750px;
font-size: 93%;
padding-bottom: 1px;
border-bottom: 4px solid #2763A5;
line-height: normal;
}
div#nav ul {
margin: 0;
padding: 0px 10px 0 48px;
list-style: none;
}
div#nav li {
display: inline;
margin: 0;
padding: 0;
}
div#nav a {
float: left;
background: url(../images/tableft10.gif) no-repeat left top;
margin: 0;
padding: 0 0 0 4px;
text-decoration: none;
}
div#nav a span {
float: left;
display: block;
background: url(../images/tabright10.gif) no-repeat right top;
padding: 3px 15px 3px 6px;
color: #FFF;
}
/**************** content styles ****************/
div#main {
width: 520px;
padding-left: 10px;
padding-right: 10px;
padding-top: 10px;
float: left;
}
div#main p {
line-height: 1.6em;
padding-bottom: 10px;
border-bottom: 1px solid #DDDDDD;
}
/**************** sidebar styles ****************/
div#sub {
width: 175px;
padding-left: 10px;
padding-right: 0px;
padding-top: 10px;
float: right;
}
div#sub h3 {
font-family: Arial, Helvetica, sans-serif;
font-size: 16px;
color: #666666;
padding-bottom: 5px;
}
div#sub p {
line-height: 1.5em;
padding-bottom: 10px;
border-bottom: 1px solid #DDDDDD;
}
/**************** footer styles ****************/
div#footer {
margin-top: 15px;
padding-top: 0px;
padding-bottom: 0px;
padding-left: 2px;
padding-right: 5px;
clear: both;
width: 742px;
background-color: #2763A5;
}
div#footer p {
color: #FFFFFF;
padding: 5px;
text-align: center;
}
div#footer p a {
color: #FFFFFF;
font-weight: 100;
border-bottom: 1px dotted #FFFFFF;
}
div#footer p {
background-color: #2763A5;
}
div#footer p a:hover {
color: #FFFFFF;
text-decoration: none;
border-top: 1px dotted #FFFFFF;
border-bottom: 0px dotted #FFFFFF;
}

View File

@ -0,0 +1,337 @@
/* A CSS Framework by Mike Stenhouse of Content with Style */
/* FORM ELEMENTS */
/* From http://www.wufoo.com/css/global/dynamic.css */
/* ----- CLASSIC WUFOO FORM ----- */
form ul{
position: relative;
list-style: none;
width: 100%;
}
form li{
line-height: 2em;
margin: 0;
padding: 1px 1px 6px 9px;
}
form li.focused{
background-color: #fff7c0 !important;
}
form li p{
font-size: 9px;
line-height: 13px;
color: #444;
}
form li{
display: inline-block;
}
form[id] li{
display: block;
}
form li div{
display: inline-block;
}
form[id] li div{
display: inline;
}
form .left{
float: left !important;
margin: 0;
}
form .right{
float: right !important;
margin: 0;
}
form .clear{
clear: both;
}
form li div p{
margin: 0 0 5px 0;
}
form div.left{
margin-right: 2px !important;
}
form div.left[class]{
margin-right: 4px !important;
}
form div.left img{
margin: 0 0 -2px 0;
}
/* ----- INFO ----- */
form h2{
font-size: 1.8em;
clear: left;
}
form .info{
display: inline-block;
margin: 0 0 10px 0;
padding: 0 0 4px 0;
border-bottom: 1px dotted #ccc !important;
}
form .info[class]{
display: block;
}
form .info p{
font-size: 1em;
line-height: 1.3em;
margin: 0 0 8px 0;
}
/* ----- SECTIONS ----- */
form .section{
display: inline-block;
border-top: 1px dotted #ccc !important;
margin-top: 15px !important;
padding-top: 12px !important;
padding-bottom: 0px !important;
}
form .section[class]{
display: block;
}
form .first{
border-top: none !important;
margin-top: 0px !important;
padding-top: 1px !important;
}
form .section h3{
font-size: 1.25em;
}
form .section p{
font-size: 11px;
line-height: 13px;
}
/* ----- FIELDS AND LABELS ----- */
label.desc{
margin: 4px 0 3px 0;
border: 0;
color: #444;
font-size: 1em;
line-height: 1.3em;
display: block;
font-weight: bold;
}
input.text, input.number, input.url, input.email, input.password, input.file,
textarea.textarea, select.select{
font-size: 1.2em;
border-top: 1px solid #7c7c7c;
border-left: 1px solid #c3c3c3;
border-right: 1px solid #c3c3c3;
border-bottom: 1px solid #ddd;
background: #fff url(../images/fieldbg.gif) repeat-x top;
color: #333;
}
input.text, input.number, input.url, input.email, input.password, input.file{
padding: 2px;
}
input.currency{
text-align: right;
}
input.checkbox, input.radio{
display: block;
line-height: 1.4em;
margin: 8px 0 0 3px;
width: 13px;
height: 13px;
}
input.focus, textarea.focus {
background: #ffd;
color: #000;
}
label.choice{
display: block;
line-height: 1.4em;
margin: -19px 0 0 25px;
padding: 4px 0 5px 0;
color: #444;
width: 80%;
}
textarea.textarea{
font-size: 1.1em;
font-family: Tahoma,"Lucida Grande", "Trebuchet MS", Verdana, sans-serif;
margin-bottom: 1px;
}
textarea.textarea[class]{
font-family: "Lucida Grande", Tahoma, "Trebuchet MS", Verdana, sans-serif;
}
select.select{
padding: 1px 0 0 0;
margin: 1px 0 3px 0;
}
select.select[class]{
margin: 0;
padding: 1px 0 1px 0;
}
/* ----- SIZES ----- */
form .small{
width: 70px;
}
form .medium{
width: 170px;
}
form .large, form textarea.textarea{
width: 340px;
}
form .tags{
width: 320px;
}
form textarea.small{
height: 5.5em;
}
form textarea.medium{
height: 10em;
}
form textarea.large{
height: 20em;
}
/* ----- ERRORS ----- */
form li.error{
background-color: #FFDFDF;
margin: 3px 0 !important;
}
input.error, textarea.error{
border: 1px solid #EF5959;
border-left: 1px solid #FF8F8F;
border-top: 1px solid #FF8F8F;
background: #fff;
}
p.error, li.error label.desc{
color: red !important;
}
p.error{
font-size: 9px !important;
margin: 1px 0;
}
/* ----- REQUIRED ----- */
.req {
font-size: 1em !important;
color: red;
font-weight: bold;
}
/* ----- Fieldsets ----- */
fieldset{
margin: 0 0 5px 0;
padding: 0 10px 10px 10px;
border: 1px solid #FFD8CF;
color: #444;
}
fieldset.choices{
padding: 10px 5px 10px 10px;
}
fieldset.fieldset{
padding: 0px 0 10px 0;
}
legend{
font-weight: bold;
margin: 0 0 0 -10px;
}
#formProperties[id] legend, .choices[class] legend{
margin: 0 0 0 -5px;
}
.fieldset legend{
margin: 0;
}
.fieldset[class] legend{
margin: 0 0 0 5px;
}
#formProperties fieldset div{
margin-bottom: 7px;
}
fieldset div .number{
margin: 7px 15px 0 0;
}
fieldset p{
margin: 10px;
}
/* ----- Choices ----- */
.choices input{
width: 200px;
margin-right: 3px;
}
.choices ol{
margin: 10px 0 0 0;
}
.choices[class] ol{
margin: 0 !important;
}
.choices img{
margin: 0 0 1px 0;
}
fieldset ol li{
display: list-item !important;
margin: 0 5px 2px 3px !important;
padding: 0 !important;
list-style: inside decimal;
}
/* ----- Buttons ----- */
input.button, button {
width: 6em;
padding: 2px 2px 0 0; /* fix for IE */
}
/* revert to normal for Firefox */
li>input.button, li>button, input.button>input.button, button>button {
padding: 2px;
}
/* END FORM ELEMENTS */

View File

@ -0,0 +1,34 @@
/* A CSS Framework by Mike Stenhouse of Content with Style */
/* NAV BAR AT THE TOP AND TWO COLUMNS OF CONTENT */
div#content {
position: relative;
width: 701px;
margin: 0 auto 20px auto;
padding: 0;
text-align: left;
}
div#main {
float: left;
width: 480px;
display: inline;
}
div#sub {
float: right;
width: 200px;
display: inline;
}
div#local {
display: none;
}
div#nav {
position: absolute;
top: -15px;
left: 0;
width: 100%;
text-align: left;
}
/* END CONTENT */

View File

@ -0,0 +1,119 @@
/* A CSS Framework by Mike Stenhouse of Content with Style */
/* SITE SPECIFIC LAYOUT */
body {
margin: 0;
padding: 0;
background: white;
text-align: center;
}
div#page {
width: 780px;
margin: 0 auto;
padding: 0;
background: white;
text-align: center;
}
/* HEADER */
div#header {
text-align: left;
}
div#branding {
float: left;
width: 40%;
margin: 0;
padding: 10px 0 10px 20px;
text-align: left;
}
div#search {
float: right;
width: 49%;
margin: 0;
padding: 16px 20px 0 0;
text-align: right;
}
/* END HEADER */
/* CONTENT */
div#content {
}
/* MAIN */
div#main {
}
/* END MAIN */
/* SUB */
div#sub {
}
/* END SUB */
/* END CONTENT */
/* FOOTER */
div#footer {
color: white;
background-color: black;
}
div#footer p {
font-size: 0.8em;
margin: 0;
padding: 15px;
}
/* END FOOTER */
/* END LAYOUT */
/* UL.SUBNAV */
ul.subnav {
margin: 0;
padding: 0;
font-size: 0.8em;
list-style: none;
}
ul.subnav li {
margin: 0 0 1em 0;
padding: 0;
list-style: none;
}
ul.subnav li a,
ul.subnav li a:link,
ul.subnav li a:visited,
ul.subnav li a:active {
text-decoration: none;
font-weight: bold;
color: black;
}
ul.subnav li a:hover {
text-decoration: underline;
}
ul.subnav li strong {
padding: 0 0 0 12px;
/*background: url(../i/subnav-highlight.gif) left top no-repeat transparent;*/
}
ul.subnav li strong a,
ul.subnav li strong a:link,
ul.subnav li strong a:visited,
ul.subnav li strong a:active {
color: white;
background-color: black;
}
/* END UL.SUBNAV */

View File

@ -0,0 +1,49 @@
table {
margin: 0px;
padding: 0px;
cell-spacing: 0px;
border-collapse: collapse;
border-bottom: 1px solid #aaa;
border-right: 1px solid #aaa;
margin-bottom: 1em;
width: 80%;
margin: 1em auto;
border-collapse: collapse;
}
th {
padding: 0.5em;
text-align: left;
border: 1px solid black;
background-color: #cccccc;
}
tfoot td {
border-top: 1px solid black;
}
td {
padding: 0.5em;
border: 1px solid black;
}
tr {
background-color: #ffffff;
}
tr.odd {
background-color: #f3f3f3;
}
td.numeric,
th.numeric {
text-align: right;
}
/** forms using table layout */
td.label {
background-color: #f3f3f3;
}

View File

@ -0,0 +1,68 @@
/* A CSS Framework by Mike Stenhouse of Content with Style */
/* clearing */
.stretch,
.clear {
clear:both;
height:1px;
margin:0;
padding:0;
font-size: 15px;
line-height: 1px;
}
.clearfix:after {
content: ".";
display: block;
height: 0;
clear: both;
visibility: hidden;
}
* html>body .clearfix {
display: inline-block;
width: 100%;
}
* html .clearfix {
/* Hides from IE-mac \*/
height: 1%;
/* End hide from IE-mac */
}
/* end clearing */
/* replace */
.replace {
display:block;
background-repeat: no-repeat;
background-position: left top;
background-color:transparent;
}
/* tidy these up */
.replace * {
text-indent: -10000px;
display:block;
background-repeat: no-repeat;
background-position: left top;
background-color:transparent;
}
.replace a {
text-indent:0;
}
.replace a span {
text-indent:-10000px;
}
/* end replace */
/* accessibility */
span.accesskey {
text-decoration:none;
}
.accessibility {
position: absolute;
top: -999em;
left: -999em;
}
/* end accessibility */

View File

@ -0,0 +1,177 @@
/* A CSS Framework by Mike Stenhouse of Content with Style */
/* TYPOGRAPHY */
body {
text-align: left;
font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;
font-size: 76%;
line-height: 1em;
color: #333;
}
div {
font-size: 1em;
}
img {
border: 0;
}
/* LINKS */
a,
a:link
a:active {
color: blue;
background-color: white;
text-decoration: underline;
}
a:visited {
color: purple;
background-color: transparent;
}
a:hover {
color: white;
background-color: black;
text-decoration: none;
}
/* END LINKS */
/* HEADINGS */
h1 {
font-size: 2em;
line-height: 1.5em;
margin: 0 0 0.5em 0;
padding: 0;
color: black;
}
h2 {
font-size: 1.5em;
line-height: 1.5em;
margin: 0 0 0.5em 0;
padding: 0;
color: black;
}
h3 {
font-size: 1.3em;
line-height: 1.3em;
margin: 0 0 0.5em 0;
padding:0;
color: black;
}
h4 {
font-size: 1.2em;
line-height: 1.3em;
margin: 0 0 0.25em 0;
padding: 0;
color: black;
}
h5 {
font-size: 1.1em;
line-height: 1.3em;
margin: 0 0 0.25em 0;
padding: 0;
color: black;
}
h6 {
font-size: 1em;
line-height: 1.3em;
margin: 0 0 0.25em 0;
padding: 0;
color: black;
}
/* END HEADINGS */
/* TEXT */
p {
font-size: 1em;
margin: 0 0 1.5em 0;
padding: 0;
line-height:1.4em;
}
blockquote {
border-left:10px solid #ddd;
margin-left:10px;
}
pre {
font-family: monospace;
font-size: 1.0em;
}
strong, b {
font-weight: bold;
}
em, i {
font-style:italic;
}
code {
font-family: "Courier New", Courier, monospace;
font-size: 1em;
white-space: pre;
}
/* END TEXT */
/* LISTS */
ul {
line-height:1.4em;
margin: 0 0 1.5em 0;
padding: 0;
}
ul li {
margin: 0 0 0.25em 30px;
padding: 0;
}
ol {
font-size: 1.0em;
line-height: 1.4em;
margin: 0 0 1.5em 0;
padding: 0;
}
ol li {
font-size: 1.0em;
margin: 0 0 0.25em 30px;
padding: 0;
}
dl {
margin: 0 0 1.5em 0;
padding: 0;
line-height: 1.4em;
}
dl dt {
font-weight: bold;
margin: 0.25em 0 0.25em 0;
padding: 0;
}
dl dd {
margin: 0 0 0 30px;
padding: 0;
}
/* END LISTS */
/* TABLE */
table {
font-size: 1em;
margin: 0 0 1.5em 0;
padding: 0;
}
table caption {
font-weight: bold;
margin: 0 0 0 0;
padding: 0 0 1.5em 0;
}
th {
font-weight: bold;
text-align: left;
}
td {
font-size: 1em;
}
/* END TABLE */
hr {
display: none;
}
div.hr {
height: 1px;
margin: 1.5em 10px;
border-bottom: 1px dotted black;
}
/* END TYPOGRAPHY */

View File

@ -0,0 +1,99 @@
<html>
<head>
<title>Durable Topic Subscribers</title>
</head>
<body>
<form action="createSubscriber.action" method="get">
<input type="hidden" name="JMSDestinationType" value="topic"/>
<table id="createSubscribers" class="sortable autostripe">
<thead>
<tr>
<th colspan="4">Create Durable Topic Subscribers</th>
</tr>
</thead>
<tbody>
<tr>
<td class="label">
<label name="clientId">Client ID</label>
</td>
<td>
<input type="text" name="clientId" value=""/>
</td>
<td class="label">
<label name="subscriberName">Subscriber Name</label>
</td>
<td>
<input type="text" name="subscriberName" value=""/>
</td>
</tr>
<tr>
<td>
<label name="JMSDestination">Topic Name</label>
</td>
<td>
<input type="text" name="JMSDestination" value=""/>
</td>
<td>
<label name="selector">JMS Selector</label>
</td>
<td>
<input type="text" name="selector" value=""/>
</td>
</tr>
<tr>
<td colspan="4" align="center">
<input type="submit" value="Create Durable Topic Subscriber"/>
</td>
</tr>
</tbody>
</table>
</form>
<h2>Durable Topic Subscribers</h2>
<table id="topics" class="sortable autostripe">
<thead>
<tr>
<th>Client ID</th>
<th>Subscription Name</th>
<th>Connection ID</th>
<th>Destination</th>
<th>Selector</th>
<th>Pending Queue Size</th>
<th>Dispatched Queue Size</th>
<th>Dispatched Counter</th>
<th>Enqueue Counter</th>
<th>Dequeue Counter</th>
<th>Operations</th>
</tr>
</thead>
<tbody>
<c:forEach items="${requestContext.brokerQuery.durableTopicSubscribers}" var="row">
<tr>
<td>${row.clientId}</td>
<td>${row.subscriptionName}</td>
<td>${row.connectionId}</td>
<td>${row.destinationName}</td>
<td>${row.selector}</td>
<td>${row.pendingQueueSize}</td>
<td>${row.dispatchedQueueSize}</td>
<td>${row.dispachedCounter}</td>
<td>${row.enqueueCounter}</td>
<td>${row.dequeueCounter}</td>
<td>
<a href="deleteSubscriber.action?clientId=${row.clientId}&subscriberName=${row.subscriptionName}">Delete</a>
</td>
</tr>
</c:forEach>
</tbody>
</table>
</body>
</html>

View File

@ -0,0 +1,36 @@
<html>
<head>
<title>Test Pages</title>
</head>
<body>
<h2>Test Pages</h2>
These pages are used to test out the environment and web framework.
<table class="autostripe">
<thead>
<tr>
<th colspan="2">Values</th>
</tr>
</thead>
<tbody>
<tr>
<td class="label">Broker type</td>
<td>${requestContext.brokerQuery.broker.class}</td>
</tr>
<tr>
<td class="label">Managed broker</td>
<td>${requestContext.brokerQuery.brokerAdmin.broker.class}</td>
</tr>
<tr>
<td class="label">Destinations</td>
<td>${requestContext.brokerQuery.managedBroker.queueRegion.destinationMap}</td>
</tr>
</tbody>
</table>
</body>
</html>

View File

@ -0,0 +1,68 @@
<html>
<head>
<title>Test Pages</title>
</head>
<body>
<h2>Test Pages</h2>
These pages are used to test out the environment and web framework.
<table class="autostripe">
<thead>
<tr>
<th colspan="2">Headers</th>
</tr>
</thead>
<tbody>
<tr>
<td class="label">request.contextPath</td>
<td>${request.contextPath}</td>
</tr>
<tr>
<td class="label">request.requestURI</td>
<td>${request.requestURI}</td>
</tr>
<tr>
<td class="label">request.remoteAddr</td>
<td>${request.remoteAddr}</td>
</tr>
<tr>
<td class="label">request.remoteHost</td>
<td>${request.remoteHost}</td>
</tr>
<tr>
<td class="label">request.queryString</td>
<td>${request.queryString}</td>
</tr>
<tr>
<td class="label">request.scheme</td>
<td>${request.scheme}</td>
</tr>
<tr>
<td class="label">request.serverName</td>
<td>${request.serverName}</td>
</tr>
<tr>
<td class="label">request.serverPort</td>
<td>${request.serverPort}</td>
</tr>
<tr>
<td class="label">Spring applicationContext</td>
<td>${applicationContext}</td>
</tr>
<tr>
<td class="label">Spring requestContext</td>
<td>${requestContext}</td>
</tr>
<tr>
<td class="label">System properties</td>
<td><%= System.getProperties() %></td>
</tr>
</tbody>
</table>
</body>
</html>

View File

@ -0,0 +1,37 @@
<html>
<head>
<title>Test Pages</title>
</head>
<body>
<h2>Test Pages</h2>
These pages are used to test out the environment and web framework.
<table class="sortable autostripe">
<thead>
<tr>
<th>System Property</th>
<th>Value</th>
</tr>
</thead>
<tbody>
<%
for (java.util.Iterator iter = System.getProperties().entrySet().iterator(); iter.hasNext(); ) {
request.setAttribute("entry", iter.next());
%>
<tr>
<td class="label">${entry.key}</td>
<td>${entry.value}</td>
</tr>
<%
}
%>
</tbody>
</table>
</body>
</html>

View File

@ -0,0 +1,49 @@
<html>
<head>
<title>Topics</title>
</head>
<body>
<div>
<form action="createDestination.action" method="get">
<input type="hidden" name="JMSDestinationType" value="topic"/>
<label name="destination">Topic Name</label>
<input type="text" name="JMSDestination" value=""/>
<input type="submit" value="Create"/>
</form>
</div>
<h2>Topics</h2>
<table id="topics" class="sortable autostripe">
<thead>
<tr>
<th>Name</th>
<th>Number Of Consumers</th>
<th>Messages Sent</th>
<th>Messages Received</th>
<th>Operations</th>
</tr>
</thead>
<tbody>
<c:forEach items="${requestContext.brokerQuery.topics}" var="row">
<tr>
<td><a href="send.jsp?JMSDestination=${row.name}&JMSDestinationType=topic">${row.name}</a></td>
<td>${row.consumerCount}</td>
<td>${row.enqueueCount}</td>
<td>${row.dequeueCount}</td>
<td>
<a href="send.jsp?JMSDestination=${row.name}&JMSDestinationType=topic">Send To</a>
<a href="deleteDestination.action?JMSDestination=${row.name}&JMSDestinationType=topic">Delete</a>
</td>
</tr>
</c:forEach>
</tbody>
</table>
</body>
</html>

View File

@ -0,0 +1,67 @@
/**
*
* Copyright 2005-2006 The Apache Software Foundation
*
* Licensed 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.tool;
import org.mortbay.jetty.Connector;
import org.mortbay.jetty.Handler;
import org.mortbay.jetty.Server;
import org.mortbay.jetty.nio.SelectChannelConnector;
import org.mortbay.jetty.webapp.WebAppContext;
/**
* A simple bootstrap class for starting Jetty in your IDE using the local web application.
*
* @version $Revision$
*/
public class Main {
public static final int PORT = 8080;
public static final String WEBAPP_DIR = "src/main/webapp";
public static final String WEBAPP_CTX = "/";
public static void main(String[] args) throws Exception {
// now lets start the web server
int port = PORT;
if (args.length > 0) {
String text = args[0];
port = Integer.parseInt(text);
}
System.out.println("Starting Web Server on port: " + port);
Server server = new Server();
SelectChannelConnector connector = new SelectChannelConnector();
connector.setPort(port);
connector.setServer(server);
WebAppContext context = new WebAppContext();
context.setResourceBase(WEBAPP_DIR);
context.setContextPath(WEBAPP_CTX);
context.setServer(server);
server.setHandlers(new Handler[]{context});
server.setConnectors(new Connector[]{connector});
server.start();
System.out.println();
System.out.println("==============================================================================");
System.out.println("Started the ActiveMQ Console: point your web browser at http://localhost:" + port + "/");
System.out.println("==============================================================================");
System.out.println();
}
}