diff options
Diffstat (limited to 'java/management')
67 files changed, 4853 insertions, 0 deletions
diff --git a/java/management/cli/bin/stac.bat b/java/management/cli/bin/stac.bat new file mode 100644 index 0000000000..156b7792cb --- /dev/null +++ b/java/management/cli/bin/stac.bat @@ -0,0 +1,38 @@ +@REM
+@REM Copyright (c) 2006 The Apache Software Foundation
+@REM
+@REM Licensed under the Apache License, Version 2.0 (the "License");
+@REM you may not use this file except in compliance with the License.
+@REM You may obtain a copy of the License at
+@REM
+@REM http://www.apache.org/licenses/LICENSE-2.0
+@REM
+@REM Unless required by applicable law or agreed to in writing, software
+@REM distributed under the License is distributed on an "AS IS" BASIS,
+@REM WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@REM See the License for the specific language governing permissions and
+@REM limitations under the License.
+@REM
+
+@echo off
+set COREROOT=..\..\core
+set AMQROOT=..\..\..\clients_java
+
+set CP=..\lib\jython\jython.jar
+set CP=%CP%;..\dist\amqp-stac.jar
+set CP=%CP%;%COREROOT%\dist\amqp-management-common.jar
+set CP=%CP%;%COREROOT%\lib\log4j\log4j-1.2.9.jar
+set CP=%CP%;%COREROOT%\lib\xmlbeans\jsr173_api.jar
+set CP=%CP%;%COREROOT%\lib\xmlbeans\resolver.jar
+set CP=%CP%;%COREROOT%\lib\xmlbeans\xbean.jar
+set CP=%CP%;%COREROOT%\lib\xmlbeans\xbean_xpath.jar
+set CP=%CP%;%COREROOT%\lib\xmlbeans\xmlpublic.jar
+set CP=%CP%;%COREROOT%\lib\xmlbeans\saxon8.jar
+set CP=%CP%;%AMQROOT%\dist\amqp-common.jar
+set CP=%CP%;%AMQROOT%\dist\amqp-jms.jar
+set CP=%CP%;%AMQROOT%\lib\mina\mina-0.7.3.jar
+set CP=%CP%;%AMQROOT%\lib\jms\jms.jar
+set CP=%CP%;%AMQROOT%\lib\util-concurrent\backport-util-concurrent.jar
+set CP=%CP%;%AMQROOT%\lib\jakarta-commons\commons-collections-3.1.jar
+
+%JAVA_HOME%\bin\java -Damqj.logging.level="ERROR" -cp %CP% org.apache.qpid.stac.Stac
diff --git a/java/management/cli/bin/stac.sh b/java/management/cli/bin/stac.sh new file mode 100755 index 0000000000..8fabe3a606 --- /dev/null +++ b/java/management/cli/bin/stac.sh @@ -0,0 +1,39 @@ +#!/bin/sh +# +# Copyright (c) 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. +# + + +COREROOT=../../core +AMQROOT=../../../clients_java + +CP=../lib/jython/jython.jar +CP=$CP:../dist/amqp-stac.jar +CP=$CP:$COREROOT/dist/amqp-management-common.jar +CP=$CP:$COREROOT/lib/log4j/log4j-1.2.9.jar +CP=$CP:$COREROOT/lib/xmlbeans/jsr173_api.jar +CP=$CP:$COREROOT/lib/xmlbeans/resolver.jar +CP=$CP:$COREROOT/lib/xmlbeans/xbean.jar +CP=$CP:$COREROOT/lib/xmlbeans/xbean_xpath.jar +CP=$CP:$COREROOT/lib/xmlbeans/xmlpublic.jar +CP=$CP:$COREROOT/lib/xmlbeans/saxon8.jar +CP=$CP:$AMQROOT/dist/amqp-common.jar +CP=$CP:$AMQROOT/dist/amqp-jms.jar +CP=$CP:$AMQROOT/lib/mina/mina-0.7.3.jar +CP=$CP:$AMQROOT/lib/jms/jms.jar +CP=$CP:$AMQROOT/lib/util-concurrent/backport-util-concurrent.jar +CP=$CP:$AMQROOT/lib/jakarta-commons/commons-collections-3.1.jar + +$JAVA_HOME/bin/java -Damqj.logging.level="ERROR" -cp $CP org.apache.qpid.stac.Stac diff --git a/java/management/cli/bin/stacDEV.bat b/java/management/cli/bin/stacDEV.bat new file mode 100644 index 0000000000..2a5bb88065 --- /dev/null +++ b/java/management/cli/bin/stacDEV.bat @@ -0,0 +1,41 @@ +@REM
+@REM Copyright (c) 2006 The Apache Software Foundation
+@REM
+@REM Licensed under the Apache License, Version 2.0 (the "License");
+@REM you may not use this file except in compliance with the License.
+@REM You may obtain a copy of the License at
+@REM
+@REM http://www.apache.org/licenses/LICENSE-2.0
+@REM
+@REM Unless required by applicable law or agreed to in writing, software
+@REM distributed under the License is distributed on an "AS IS" BASIS,
+@REM WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@REM See the License for the specific language governing permissions and
+@REM limitations under the License.
+@REM
+
+@echo off
+set COREROOT=..\..\core
+set AMQROOT=..\..\..\clients_java
+
+set CP=..\lib\jython\jython.jar
+set CP=%CP%;..\intellijclasses
+set CP=%CP%;%COREROOT%\intellijclasses
+set CP=%CP%;%COREROOT%\classes
+set CP=%CP%;%COREROOT%\lib\log4j\log4j-1.2.9.jar
+set CP=%CP%;%COREROOT%\lib\xmlbeans\jsr173_api.jar
+set CP=%CP%;%COREROOT%\lib\xmlbeans\resolver.jar
+set CP=%CP%;%COREROOT%\lib\xmlbeans\xbean.jar
+set CP=%CP%;%COREROOT%\lib\xmlbeans\xbean_xpath.jar
+set CP=%CP%;%COREROOT%\lib\xmlbeans\xmlpublic.jar
+set CP=%CP%;%COREROOT%\lib\xmlbeans\saxon8.jar
+set CP=%CP%;%AMQROOT%\dist\amqp-common.jar
+set CP=%CP%;%AMQROOT%\dist\amqp-jms.jar
+set CP=%CP%;%AMQROOT%\lib\mina\mina-0.7.3.jar
+set CP=%CP%;%AMQROOT%\lib\jms\jms.jar
+set CP=%CP%;%AMQROOT%\lib\util-concurrent\backport-util-concurrent.jar
+set CP=%CP%;%AMQROOT%\lib\jakarta-commons\commons-collections-3.1.jar
+
+
+@rem %JAVA_HOME%\bin\java -Damqj.logging.level="ERROR" -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005 -cp %CP% org.amqp.blaze.stac.Stac
+%JAVA_HOME%\bin\java -Damqj.logging.level="ERROR" -cp %CP% org.amqp.blaze.stac.Stac
\ No newline at end of file diff --git a/java/management/cli/build-module.xml b/java/management/cli/build-module.xml new file mode 100644 index 0000000000..2c52418e46 --- /dev/null +++ b/java/management/cli/build-module.xml @@ -0,0 +1,21 @@ +<!-- + - + - Copyright (c) 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 name="AMQ Management Client" default="build"> + <property name="module.depends" value="common,client,management/core"/> + <import file="../../module.xml"/> +</project> diff --git a/java/management/cli/build-old.xml b/java/management/cli/build-old.xml new file mode 100644 index 0000000000..8445e4484f --- /dev/null +++ b/java/management/cli/build-old.xml @@ -0,0 +1,122 @@ +<?xml version="1.0"?> +<!-- + - + - Copyright (c) 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. + - + --> + +<!-- AMQP STAC Java build file --> + +<project name="management-stac" default="jar" basedir="."> + <property name="lib" value="${basedir}/lib"/> + <property name="src" value="${basedir}/src"/> + <property name="tests" value="${basedir}/test"/> + <property name="classes" value="${basedir}/classes"/> + <property name="testclasses" value="${basedir}/testclasses"/> + <property name="dist" value="${basedir}/dist"/> + <property name="amqp.root" value="${basedir}/../../clients_java"/> + <property name="amqp.lib" value="${amqp.root}/lib"/> + <property name="amqp.dist" value="${amqp.root}/dist"/> + <property name="managementcore.root" value="${basedir}/../core"/> + <property name="managementcore.dist" value="${managementcore.root}/dist"/> + <property name="managementcore.lib" value="${managementcore.root}/lib"/> + + <!-- Setup details --> + <target name="init"> + <tstamp> + <format property="release" pattern="-dMMMyy" locale="en" timezone="GMT"/> + </tstamp> + + <mkdir dir="${classes}"/> + <mkdir dir="${testclasses}"/> + <mkdir dir="${dist}"/> + </target> + + <path id="core.classpath"> + <fileset dir="${lib}"> + <include name="**/*.jar"/> + </fileset> + <pathelement path="${classes}"/> + <pathelement path="${testclasses}/"/> + <fileset dir="${managementcore.dist}"> + <include name="**/*.jar"/> + </fileset> + <fileset dir="${managementcore.lib}"> + <include name="**/*.jar"/> + </fileset> + <fileset dir="${amqp.dist}"> + <include name="**/*.jar"/> + </fileset> + <fileset dir="${amqp.lib}"> + <include name="**/*.jar"/> + </fileset> + </path> + + <!-- Remove all built files --> + <target name="clean" depends="init"> + <delete dir="${classes}"/> + <delete dir="${dist}"/> + <delete dir="${testclasses}"/> + </target> + + <!-- Compile Java --> + <target name="compile" depends="init"> + <javac destdir="${classes}" target="1.5" source="1.5" debug="on"> + <classpath refid="core.classpath"/> + <src path="${src}"/> + </javac> + + <copy todir="${classes}"> + <!-- copy any non java src files into the build tree, e.g. log4j.properties --> + <fileset dir="${src}"> + <exclude name="**/*.java"/> + <exclude name="**/package.html"/> + </fileset> + </copy> + </target> + + + <target name="compiletests" depends="compile"> + <javac destdir="${testclasses}" target="1.5" source="1.5" classpathref="core.classpath" + debug="on"> + <src path="${tests}"/> + </javac> + + <copy todir="${testclasses}"> + <!-- copy any non java src files into the build tree, e.g. log4j.properties --> + <fileset dir="${tests}"> + <exclude name="**/*.java"/> + <exclude name="**/package.html"/> + </fileset> + </copy> + </target> + + <!-- Build jar archive --> + <target name="jar" depends="compiletests"> + <mkdir dir="${dist}"/> + <jar basedir="${classes}" jarfile="${dist}/amqp-stac.jar"/> + <jar basedir="${testclasses}" jarfile="${dist}/amqp-stac-tests.jar"/> + </target> + + + <target name="javadoc" depends="compile, compiletests"> + <mkdir dir="${dist}/docs/api"/> + <javadoc sourcepath="${src}" destdir="${dist}/docs/api" + packagenames="org.apache.qpid.*" classpathref="amqp.classpath" author="true" + version="true" windowTitle="AMQP STAC API" doctitle="AMQP STAC API" + footer="See <a href="http://www.amqp.org">www.amqp.org</a> for more information." + use="true" verbose="false"/> + </target> +</project> diff --git a/java/management/cli/lib/jython/jython.jar b/java/management/cli/lib/jython/jython.jar Binary files differnew file mode 100644 index 0000000000..517c60dd0e --- /dev/null +++ b/java/management/cli/lib/jython/jython.jar diff --git a/java/management/cli/src/org/apache/qpid/stac/Stac.java b/java/management/cli/src/org/apache/qpid/stac/Stac.java new file mode 100644 index 0000000000..98633286fb --- /dev/null +++ b/java/management/cli/src/org/apache/qpid/stac/Stac.java @@ -0,0 +1,94 @@ +/* + * + * Copyright (c) 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.qpid.stac; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.InputStream; + +public class Stac +{ + public static void main(String[] args) + { + BufferedReader terminal = new BufferedReader(new InputStreamReader(System.in)); + System.out.println("\nInitializing the Scripting Tool for AMQ Console (STAC) ..."); + String var = System.getProperty("python.verbose"); + if (var != null) + { + System.setProperty("python.verbose", var); + } + else + { + System.setProperty("python.verbose", "warning"); + } + StacInterpreter interp = new StacInterpreter(); + InputStream is = Stac.class.getResourceAsStream("/python/stac.py"); + if (is == null) + { + System.err.println("Unable to load STAC Python library. Terminating."); + System.exit(1); + } + interp.execfile(is); + + boolean running = true; + + while (running) + { + interp.write(interp.get("commandPrompt").toString()); + + String line = null; + try + { + line = terminal.readLine(); + if (line != null) + { + if (line.equalsIgnoreCase("quit") || line.equalsIgnoreCase("exit")) + { + running = false; + line = "quit()"; + } + while (interp.runsource(line)) + { + interp.write("..."); + try + { + String s = terminal.readLine(); + line = line + "\n" + s; + } + catch (IOException e) + { + e.printStackTrace(); + } + } + } + else + { + System.out.println(); + running = false; + } + } + catch (IOException ie) + { + System.err.println("An error occurred: " + ie); + ie.printStackTrace(System.err); + } + } + System.exit(0); + } +} diff --git a/java/management/cli/src/org/apache/qpid/stac/StacInterpreter.java b/java/management/cli/src/org/apache/qpid/stac/StacInterpreter.java new file mode 100644 index 0000000000..14f9a34504 --- /dev/null +++ b/java/management/cli/src/org/apache/qpid/stac/StacInterpreter.java @@ -0,0 +1,31 @@ +/* + * + * Copyright (c) 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.qpid.stac; + +import org.python.util.InteractiveInterpreter; +import org.python.core.PySystemState; + +public class StacInterpreter extends InteractiveInterpreter +{ + public StacInterpreter() + { + PySystemState.initialize(); + super.set("theInterpreter", this); + super.exec("import sys\n"); + } +} diff --git a/java/management/cli/src/org/apache/qpid/stac/commands/CdCommand.java b/java/management/cli/src/org/apache/qpid/stac/commands/CdCommand.java new file mode 100644 index 0000000000..b21bc450bd --- /dev/null +++ b/java/management/cli/src/org/apache/qpid/stac/commands/CdCommand.java @@ -0,0 +1,50 @@ +/* + * + * Copyright (c) 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.qpid.stac.commands; + +import org.apache.qpid.stac.jmx.MBeanServerConnectionContext; +import org.apache.qpid.stac.jmx.CurrentMBean; +import org.apache.qpid.AMQException; + +public class CdCommand +{ + public static void execute(MBeanServerConnectionContext context, String destination) + throws AMQException + { + // check if it is an absolute path and if so change to the root first + if (destination.startsWith("/")) + { + context.changeBean("/"); + destination = destination.substring(1); + } + if (destination.length() == 0) + { + return; + } + String[] destinations = destination.split("/"); + for (String item : destinations) + { + if ("..".equals(item)) + { + item = CurrentMBean.PARENT_ATTRIBUTE; + } + context.changeBean(item); + } + } + +} diff --git a/java/management/cli/src/org/apache/qpid/stac/commands/InvokeCommand.java b/java/management/cli/src/org/apache/qpid/stac/commands/InvokeCommand.java new file mode 100644 index 0000000000..68b4a6f8aa --- /dev/null +++ b/java/management/cli/src/org/apache/qpid/stac/commands/InvokeCommand.java @@ -0,0 +1,31 @@ +/* + * + * Copyright (c) 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.qpid.stac.commands; + +import org.apache.qpid.stac.jmx.MBeanServerConnectionContext; +import org.apache.qpid.AMQException; + +public class InvokeCommand +{ + public static void execute(MBeanServerConnectionContext context, String methodName, Object... args) + throws AMQException + { + // Not used currently + + } +} diff --git a/java/management/cli/src/org/apache/qpid/stac/commands/LsCommand.java b/java/management/cli/src/org/apache/qpid/stac/commands/LsCommand.java new file mode 100644 index 0000000000..4cfa96b030 --- /dev/null +++ b/java/management/cli/src/org/apache/qpid/stac/commands/LsCommand.java @@ -0,0 +1,123 @@ +/* + * + * Copyright (c) 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.qpid.stac.commands; + +import org.apache.qpid.AMQException; +import org.apache.qpid.stac.jmx.CurrentMBean; +import org.apache.qpid.stac.jmx.MBeanServerConnectionContext; +import org.apache.qpid.stac.jmx.MBeanUtils; + +import javax.management.MBeanAttributeInfo; +import javax.management.MBeanOperationInfo; +import javax.management.MBeanParameterInfo; +import java.util.SortedSet; + +public class LsCommand +{ + public static void execute(MBeanServerConnectionContext context) + throws AMQException + { + CurrentMBean currentMBean = context.getCurrentMBean(); + + SortedSet<MBeanAttributeInfo> directories = currentMBean.getOrderedObjects(); + System.out.println(); + for (MBeanAttributeInfo ai : directories) + { + if (!MBeanUtils.isHidden(ai)) + { + outputAccess(ai); + System.out.println(" " + ai.getName()); + } + } + System.out.println(); + + SortedSet<MBeanAttributeInfo> attributes = currentMBean.getOrderedAttributes(); + for (MBeanAttributeInfo ai : attributes) + { + outputAccess(ai); + System.out.printf(" %1$-15s%2$-15s %3$s\n", ai.getName(), "[" + convertType(ai.getType()) + "]", + currentMBean.getAttributeValue(ai.getName(), ai.getType())); + } + System.out.println(); + SortedSet<MBeanOperationInfo> operations = currentMBean.getOrderedOperations(); + + for (MBeanOperationInfo oi : operations) + { + System.out.printf("-r-x %1$-15s", oi.getName()); + MBeanParameterInfo[] paramInfos = oi.getSignature(); + System.out.print("["); + if (paramInfos.length == 0) + { + System.out.print("No arguments"); + } + + for (int i = 0; i < paramInfos.length; i++) + { + MBeanParameterInfo pi = paramInfos[i]; + System.out.printf("%1$s:%2$s%3$s", pi.getName(), convertType(pi.getType()), + (i < paramInfos.length)?",":""); + } + System.out.println("]"); + } + System.out.println(); + } + + private static void outputAccess(MBeanAttributeInfo ai) + { + boolean isObject = ai.getType().equals("javax.management.ObjectName"); + System.out.print(isObject?"d":"-"); + System.out.print(ai.isReadable()?"r":"-"); + System.out.print(ai.isWritable()?"w":"-"); + System.out.print("-"); + } + + /** + * Converts the type name to a non-Java type (e.g. java.lang.String -> String) + * @param javaType + * @return a generic type + */ + private static String convertType(String javaType) + { + if ("java.lang.String".equals(javaType)) + { + return "String"; + } + else if ("java.lang.Integer".equals(javaType)) + { + return "Integer"; + } + else if ("java.lang.Boolean".equals(javaType)) + { + return "Boolean"; + } + else if ("java.lang.Double".equals(javaType)) + { + return "Double"; + } + else if ("java.util.Date".equals(javaType)) + { + return "Date"; + } + else + { + return javaType; + } + } + + +} diff --git a/java/management/cli/src/org/apache/qpid/stac/jmx/CurrentMBean.java b/java/management/cli/src/org/apache/qpid/stac/jmx/CurrentMBean.java new file mode 100644 index 0000000000..d378329220 --- /dev/null +++ b/java/management/cli/src/org/apache/qpid/stac/jmx/CurrentMBean.java @@ -0,0 +1,180 @@ +/* + * + * Copyright (c) 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.qpid.stac.jmx; + +import org.apache.qpid.AMQException; + +import javax.management.*; +import java.text.SimpleDateFormat; +import java.util.*; + +/** + * Stores information about the "current" MBean. This data is used when navigating the hierarchy. + * + * For example, we need to map between a name and an object id, and this stores that link. + * + */ +public class CurrentMBean +{ + private MBeanServerConnection _mbeanServerConnection; + + public static final String PARENT_ATTRIBUTE = "__parent"; + + private static final SimpleDateFormat _dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + /** + * Maps names to ObjectNames. Used for efficiency to avoid iterating through all names when doing a CD command. + */ + private Map<String, ObjectName> _name2ObjectNameMap = new HashMap<String, ObjectName>(); + + private ObjectName _mbeanObjectName; + + private MBeanInfo _mbeanInfo; + + public CurrentMBean(MBeanServerConnection mbeanServerConnection) + { + _mbeanServerConnection = mbeanServerConnection; + } + + public void changeMBean(ObjectName objectName) throws AMQException + { + try + { + _mbeanInfo = _mbeanServerConnection.getMBeanInfo(objectName); + } + catch (Exception e) + { + throw new AMQException("Unable to look up MBean for object name " + objectName + ": " + e, e); + } + _mbeanObjectName = objectName; + } + + public ObjectName getMBeanObjectName() + { + return _mbeanObjectName; + } + + public MBeanInfo getMBeanInfo() + { + return _mbeanInfo; + } + + public Object getAttributeValue(String name, String type) throws AMQException + { + // TODO: The type argument is a temporary workaround for a bug (somewhere!) in which + // a date is returned as a String + try + { + Object o = _mbeanServerConnection.getAttribute(_mbeanObjectName, name); + if ("java.util.Date".equals(type)) + { + + return _dateFormat.format(new Date(Long.parseLong((String)o))); + } + else + { + return o; + } + } + catch (Exception e) + { + throw new AMQException("Unable to read attribute value for attribute name " + name, e); + } + } + + /** + * Get the objects (i.e. "directories") under the current mbean, ordered alphabetically. This method also + * refreshes the cache that maps from name to ObjectName (this saves iterating through the attributes again). + * @return a set containing the attribute infos, sorted by name + */ + public SortedSet<MBeanAttributeInfo> getOrderedObjects() throws AMQException + { + TreeSet<MBeanAttributeInfo> attributes = new TreeSet<MBeanAttributeInfo>(new MBeanAttributeInfoComparator()); + _name2ObjectNameMap.clear(); + for (MBeanAttributeInfo ai : _mbeanInfo.getAttributes()) + { + String type = ai.getType(); + + if ("javax.management.ObjectName".equals(type)) + { + _name2ObjectNameMap.put(ai.getName(), (ObjectName)getAttributeValue(ai.getName(), type)); + attributes.add(ai); + } + } + return attributes; + } + + public void refreshNameToObjectNameMap() throws AMQException + { + _name2ObjectNameMap.clear(); + for (MBeanAttributeInfo ai : _mbeanInfo.getAttributes()) + { + final String type = ai.getType(); + + if ("javax.management.ObjectName".equals(type)) + { + _name2ObjectNameMap.put(ai.getName(), (ObjectName)getAttributeValue(ai.getName(), type)); + } + } + } + + /** + * Gets an object name, given the "display name" + * @param name the display name (usually returned to the user when he does an ls() + * @return the object name + */ + public ObjectName getObjectNameByName(String name) + { + return _name2ObjectNameMap.get(name); + } + + public SortedSet<MBeanAttributeInfo> getOrderedAttributes() + { + TreeSet<MBeanAttributeInfo> attributes = new TreeSet<MBeanAttributeInfo>(new MBeanAttributeInfoComparator()); + for (MBeanAttributeInfo ai : _mbeanInfo.getAttributes()) + { + String type = ai.getType(); + if (!"javax.management.ObjectName".equals(type)) + { + attributes.add(ai); + } + } + return attributes; + } + + public SortedSet<MBeanOperationInfo> getOrderedOperations() + { + TreeSet<MBeanOperationInfo> operations = new TreeSet<MBeanOperationInfo>(new MBeanOperationInfoComparator()); + for (MBeanOperationInfo oi : _mbeanInfo.getOperations()) + { + operations.add(oi); + } + return operations; + } + + public void invoke(String methodName, Object... args) throws AMQException + { + try + { + _mbeanServerConnection.invoke(_mbeanObjectName, methodName, null, null); + } + catch (Exception e) + { + throw new AMQException("Error invoking method " + methodName + ": " + e, e); + } + } +} diff --git a/java/management/cli/src/org/apache/qpid/stac/jmx/MBeanAttributeInfoComparator.java b/java/management/cli/src/org/apache/qpid/stac/jmx/MBeanAttributeInfoComparator.java new file mode 100644 index 0000000000..b5c2437d58 --- /dev/null +++ b/java/management/cli/src/org/apache/qpid/stac/jmx/MBeanAttributeInfoComparator.java @@ -0,0 +1,29 @@ +/* + * + * Copyright (c) 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.qpid.stac.jmx; + +import javax.management.MBeanAttributeInfo; +import java.util.Comparator; + +public class MBeanAttributeInfoComparator implements Comparator<MBeanAttributeInfo> +{ + public int compare(MBeanAttributeInfo o1, MBeanAttributeInfo o2) + { + return o1.getName().compareTo(o2.getName()); + } +} diff --git a/java/management/cli/src/org/apache/qpid/stac/jmx/MBeanOperationInfoComparator.java b/java/management/cli/src/org/apache/qpid/stac/jmx/MBeanOperationInfoComparator.java new file mode 100644 index 0000000000..4c490d92d5 --- /dev/null +++ b/java/management/cli/src/org/apache/qpid/stac/jmx/MBeanOperationInfoComparator.java @@ -0,0 +1,29 @@ +/* + * + * Copyright (c) 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.qpid.stac.jmx; + +import javax.management.MBeanOperationInfo; +import java.util.Comparator; + +public class MBeanOperationInfoComparator implements Comparator<MBeanOperationInfo> +{ + public int compare(MBeanOperationInfo o1, MBeanOperationInfo o2) + { + return o1.getName().compareTo(o2.getName()); + } +} diff --git a/java/management/cli/src/org/apache/qpid/stac/jmx/MBeanServerConnectionContext.java b/java/management/cli/src/org/apache/qpid/stac/jmx/MBeanServerConnectionContext.java new file mode 100644 index 0000000000..18e5359b8c --- /dev/null +++ b/java/management/cli/src/org/apache/qpid/stac/jmx/MBeanServerConnectionContext.java @@ -0,0 +1,202 @@ +/* + * + * Copyright (c) 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.qpid.stac.jmx; + +import org.apache.qpid.AMQException; +import org.apache.qpid.management.jmx.JmxConstants; +import org.apache.qpid.stac.commands.CdCommand; +import org.apache.qpid.stac.commands.LsCommand; +import org.apache.log4j.Logger; + +import javax.management.MBeanServerConnection; +import javax.management.MalformedObjectNameException; +import javax.management.ObjectName; +import javax.management.ObjectInstance; +import javax.management.remote.JMXConnector; +import javax.management.remote.JMXConnectorFactory; +import javax.management.remote.JMXServiceURL; +import java.lang.management.ManagementFactory; +import java.util.Hashtable; +import java.util.Set; + +public class MBeanServerConnectionContext +{ + private static final Logger _log = Logger.getLogger(MBeanServerConnectionContext.class); + + /** + * The connection to the MBean server. Can be remote or local, depending on whether we are proxying. + */ + private MBeanServerConnection _connection; + + /** + * The connector used to make the connection to the remote MBean server + */ + private JMXConnector _connector; + + private CurrentMBean _currentMBean; + + /* + * Initialize connection to the Domain Runtime MBean Server + */ + public void connect(String host) throws AMQException + { + if (host == null) + { + _connection = (MBeanServerConnection) ManagementFactory.getPlatformMBeanServer(); + } + else + { + String serviceURLString = "service:jmx:local://localhost"; + + try + { + JMXServiceURL serviceURL = new JMXServiceURL(serviceURLString); + _connector = JMXConnectorFactory.connect(serviceURL, null); + _connection = _connector.getMBeanServerConnection(); + } + catch (Exception e) + { + throw new AMQException("Unable to connect to remote MBean server with service url " + serviceURLString + + ": " + e, e); + } + } + _currentMBean = new CurrentMBean(_connection); + changeBean(getRootObjectName()); + } + + /** + * Connect to the local MBean server + * @throws AMQException + */ + public void connect() throws AMQException + { + connect(null); + } + + public void disconnect() throws AMQException + { + if (_connection != null) + { + try + { + ObjectName queryName = new ObjectName(JmxConstants.JMX_DOMAIN + ":*"); + Set<ObjectInstance> beans = _connection.queryMBeans(queryName, null); + for (ObjectInstance bean : beans) + { + _log.debug("Unregistering MBean: " + bean.getObjectName()); + _connection.unregisterMBean(bean.getObjectName()); + } + } + catch (Exception e) + { + throw new AMQException("Error unregistering MBeans: " + e, e); + } + } + } + + public ObjectName getRootObjectName() throws AMQException + { + Hashtable<String, String> props = new Hashtable<String, String>(); + props.put("objectid", "0"); + props.put("type", "broker"); + try + { + return new ObjectName(JmxConstants.JMX_DOMAIN, props); + } + catch (MalformedObjectNameException e) + { + throw new AMQException("Cannot construct root MBean object name: " + e, e); + } + } + + private void changeBean(ObjectName objectName) throws AMQException + { + _currentMBean.changeMBean(objectName); + } + + /** + * Change the current bean to the one underneath the current bean, represented by the display name + * @param name + * @throws AMQException + */ + public void changeBean(String name) throws AMQException + { + checkConnection(); + if (name.equals("/")) + { + changeBean(getRootObjectName()); + } + else + { + ObjectName objName = _currentMBean.getObjectNameByName(name); + if (CurrentMBean.PARENT_ATTRIBUTE.equals(name) && objName == null) + { + // we have tried to change up a level from the root, so just ignore + return; + } + if (objName == null) + { + // could be stale cache, so refresh + _currentMBean.refreshNameToObjectNameMap(); + objName = _currentMBean.getObjectNameByName(name); + } + if (objName == null) + { + throw new AMQException("Unknown managed object with name: " + name); + } + else + { + changeBean(objName); + } + } + } + + public void ls() throws AMQException + { + checkConnection(); + LsCommand.execute(this); + } + + public void cd(String destination) throws AMQException + { + CdCommand.execute(this, destination); + } + + public void invoke(String methodName, Object... args) throws AMQException + { + _currentMBean.invoke(methodName, args); + } + + public CurrentMBean getCurrentMBean() + { + return _currentMBean; + } + + public MBeanServerConnection getMBeanServerConnection() + { + return _connection; + } + + private void checkConnection() throws NotConnectedException + { + if (_connection == null) + { + throw new NotConnectedException(); + } + } +} diff --git a/java/management/cli/src/org/apache/qpid/stac/jmx/MBeanUtils.java b/java/management/cli/src/org/apache/qpid/stac/jmx/MBeanUtils.java new file mode 100644 index 0000000000..57bba9d4d3 --- /dev/null +++ b/java/management/cli/src/org/apache/qpid/stac/jmx/MBeanUtils.java @@ -0,0 +1,35 @@ +/* + * + * Copyright (c) 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.qpid.stac.jmx; + +import javax.management.MBeanAttributeInfo; + +/** + * Useful MBean methods. Also provides functionality for our CMLMBean + */ +public class MBeanUtils +{ + public static boolean isHidden(MBeanAttributeInfo ai) + { + /* This is JDK 1.6 only + String hidden = (String) ai.getDescriptor().getFieldValue("hidden"); + return hidden != null && "true".equals(hidden); + */ + return ai.getName().startsWith("__"); + } +} diff --git a/java/management/cli/src/org/apache/qpid/stac/jmx/NotConnectedException.java b/java/management/cli/src/org/apache/qpid/stac/jmx/NotConnectedException.java new file mode 100644 index 0000000000..2fcb6e5ddf --- /dev/null +++ b/java/management/cli/src/org/apache/qpid/stac/jmx/NotConnectedException.java @@ -0,0 +1,28 @@ +/* + * + * Copyright (c) 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.qpid.stac.jmx; + +import org.apache.qpid.AMQException; + +public class NotConnectedException extends AMQException +{ + public NotConnectedException() + { + super("Not connected to JMX server"); + } +} diff --git a/java/management/cli/src/python/stac.py b/java/management/cli/src/python/stac.py new file mode 100644 index 0000000000..d521dc18c3 --- /dev/null +++ b/java/management/cli/src/python/stac.py @@ -0,0 +1,190 @@ +# +# Copyright (c) 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. +# + +""" +Bridges between Python and Java, to provide a simpler and more Pythonesque environment. +Certified to be free of dead parrots. +""" +# Imports +from java.lang import * +import org.amqp.blaze.management.jmx.AMQConsole as AMQConsole +import org.amqp.blaze.stac.jmx.MBeanServerConnectionContext as MBeanServerConnectionContext + +# Globals +commandPrompt = "" +proxied = 0 +connected = 0 +amqConsole = None +connectionContext = None + +# Functions +def connect(url="", username="", password=""): + """ + Connects to an AMQP broker. The URL must be in the form amq://host:port/context + """ + try: + global connected + global connectionContext + if connected==1: + print "Already Connected!" + return + + try: + parsedURL = parseURL(url) + except URLFormatError, ufe: + print "Invalid URL: " + ufe.msg + return + + amqConsole = AMQConsole(parsedURL['host'], parsedURL['port'], username, password, parsedURL['context']) + + amqConsole.initialise() + amqConsole.registerAllMBeans() + connectionContext = MBeanServerConnectionContext() + connectionContext.connect() + connected = 1 + except Exception, e: + updateGlobals() + print e + e.printStackTrace() + cause = e.getCause() + if cause != None: + cause.printStackTrace() + else: + updateGlobals(); + +def disconnect(): + """ + Disconnects from the broker + """ + global connected + global connectionContext + + if connected==0: + print "Not connected!" + return + try: + connectionContext.disconnect() + connected = 0 + except Exception, e: + updateGlobals() + print e + else: + updateGlobals() + +def quit(): + global connected + if connected != 0: + disconnect() + +def ls(): + """ + Lists the current mbean + """ + global connected + if connected == 0: + print "Not connected!" + return + + connectionContext.ls() + +def cd(beanName): + """ + Changes the current mbean + """ + global connected + global connectionContext + if connected == 0: + print "Not connected!" + return + + try: + connectionContext.cd(beanName) + except Exception, e: + updateGlobals() + msg = "Error: " + e.getMessage() + print msg + else: + updateGlobals() + +def invoke(methodName): + """ + Invokes an operation of the current mbean + """ + global connected + global connectionContext + + if connected == 0: + print "Not connected!" + return + + try: + connectionContext.invoke(methodName, None) + except Exception, e: + updateGlobals() + msg = "Error: " + e.getMessage() + print msg + else: + updateGlobals() + +class URLFormatError(Exception): + """Exception raised for errors in format of the URL + + Attributes: + expression -- input expression in which the error occurred + message -- explanation of the error + """ + + def __init__(self, url, message): + self.url = url + self.msg = message + +def parseURL(url): + """ + Parses an AMQ URL into host, port and context components returning them in a dictionary + """ + idx = url.find("amq://") + errorMsg = "Invalid URL - must be format amq://hostname:port/vhost" + if idx != 0: + raise URLFormatError(url, errorMsg) + + hostEndIdx = url.find(":", 6) + if hostEndIdx == -1: + raise URLFormatError(url, errorMsg) + + hostname = url[6:hostEndIdx] + + portIdx = url.find("/", hostEndIdx + 1) + port = url[hostEndIdx + 1:portIdx] + vhost = url[portIdx + 1:] + if portIdx == -1: + raise URLFormatError(url, errorMsg) + + return {'host':hostname,'port':int(port),'context':vhost} + +def updateGlobals(): + global commandPrompt + global connectionContext + if connected == 1: + commandPrompt = "AMQ:connected#" + connectionContext.getCurrentMBean().getAttributeValue("name", "java.lang.String") + "> " + else: + commandPrompt = "AMQ:disconnected> " +# Classes + + +# Global execution + +# Update all the global variables - this is called to sync everything at the start +updateGlobals() diff --git a/java/management/cli/test/org/apache/qpid/stac/ConnectionTest.java b/java/management/cli/test/org/apache/qpid/stac/ConnectionTest.java new file mode 100644 index 0000000000..cf728cc6aa --- /dev/null +++ b/java/management/cli/test/org/apache/qpid/stac/ConnectionTest.java @@ -0,0 +1,35 @@ +/* + * + * Copyright (c) 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.qpid.stac; + +import org.apache.qpid.management.jmx.AMQConsole; +import org.apache.qpid.stac.jmx.MBeanServerConnectionContext; + +public class ConnectionTest +{ + public static void main(String[] args) throws Exception + { + + AMQConsole console = new AMQConsole("localhost", 5672, "guest", "guest", "/test"); + console.initialise(); + console.registerAllMBeans(); + MBeanServerConnectionContext connectionContext = new MBeanServerConnectionContext(); + connectionContext.connect(); + connectionContext.ls(); + } +} diff --git a/java/management/core/build-module.xml b/java/management/core/build-module.xml new file mode 100644 index 0000000000..07e17a44d4 --- /dev/null +++ b/java/management/core/build-module.xml @@ -0,0 +1,47 @@ +<!-- + - + - Copyright (c) 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 name="AMQ Management Core" default="build"> + + <property name="module.depends" value="common,client"/> + + <import file="../../module.xml"/> + + <property name="etc" value="etc"/> + <property name="xmlbeans.timestamp" value="${module.dir}/xmlbeans.timestamp"/> + + <fileset id="xmlbeans.schema" dir="${etc}" includes="**/*.xsd"/> + + <uptodate property="xmlbeans.done" targetfile="${xmlbeans.timestamp}"> + <srcfiles refid="xmlbeans.schema"/> + </uptodate> + + <taskdef name="xmlbean" classname="org.apache.xmlbeans.impl.tool.XMLBean" classpathref="module.class.path"/> + + <!-- Generate code from the XML schema --> + <target name="xmlbeans" unless="xmlbeans.done"> + <xmlbean classgendir="${module.classes}" classpathref="module.class.path" + failonerror="true" srcgendir="${module.precompiled}" + javasource="1.5" source="1.5"> + <fileset refid="xmlbeans.schema"/> + </xmlbean> + <touch file="${xmlbeans.timestamp}"/> + </target> + + <target name="precompile" depends="xmlbeans"/> + +</project> diff --git a/java/management/core/build-old.xml b/java/management/core/build-old.xml new file mode 100644 index 0000000000..df00b95bcc --- /dev/null +++ b/java/management/core/build-old.xml @@ -0,0 +1,189 @@ +<?xml version="1.0"?> +<!-- + - + - Copyright (c) 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. + - + --> + +<!-- AMQP Management Core Java build file --> + +<project name="management-core" default="jar" basedir="."> + <property name="lib" value="${basedir}/lib"/> + <property name="src" value="${basedir}/src"/> + <property name="generated.src" value="${basedir}/generated/src"/> + <property name="tests" value="${basedir}/test"/> + <property name="etc" value="${basedir}/etc"/> + <property name="classes" value="${basedir}/classes"/> + <property name="testclasses" value="${basedir}/testclasses"/> + <property name="dist" value="${basedir}/dist"/> + <property name="apache.root" value="${basedir}/../../clients_java"/> + <property name="apache.dist" value="${apache.root}/dist"/> + <property name="apache.lib" value="${apache.root}/lib"/> + + <taskdef name="xmlbean" classname="org.apache.xmlbeans.impl.tool.XMLBean" classpathref="core.classpath"/> + + <!-- Setup details --> + <target name="init"> + <tstamp> + <format property="release" pattern="-dMMMyy" locale="en" timezone="GMT"/> + </tstamp> + + <mkdir dir="${generated.src}"/> + <mkdir dir="${classes}"/> + <mkdir dir="${testclasses}"/> + <mkdir dir="${dist}"/> + </target> + + <path id="core.classpath"> + <fileset dir="${lib}"> + <include name="**/*.jar"/> + </fileset> + <pathelement path="${classes}"/> + <pathelement path="${testclasses}/"/> + <fileset dir="${apache.dist}"> + <include name="**/*.jar"/> + </fileset> + <fileset dir="${apache.lib}"> + <include name="**/*.jar"/> + </fileset> + </path> + + <!-- Remove all built files --> + <target name="clean" depends="init"> + <delete dir="${generated.src}"/> + <delete dir="${classes}"/> + <delete dir="${dist}"/> + <delete dir="${testclasses}"/> + </target> + + <!-- Generate code from the XML schema --> + <target name="xmlbeans" depends="init"> + <xmlbean classgendir="${classes}" classpathref="core.classpath" + failonerror="true" srcgendir="${generated.src}" + javasource="1.5" source="1.5"> + <fileset dir="${etc}" includes="**/*.xsd"/> + </xmlbean> + </target> + + <!-- Compile Java --> + <target name="compile" depends="xmlbeans"> + <javac destdir="${classes}" target="1.5" source="1.5" debug="on"> + <classpath refid="core.classpath"/> + <src path="${src}"/> + <src path="${generated.src}"/> + </javac> + + <copy todir="${classes}"> + <!-- copy any non java src files into the build tree, e.g. log4j.properties --> + <fileset dir="${src}"> + <exclude name="**/*.java"/> + <exclude name="**/package.html"/> + </fileset> + </copy> + </target> + + + <target name="compiletests" depends="compile"> + <javac destdir="${testclasses}" target="1.5" source="1.5" classpathref="core.classpath" + debug="on"> + <src path="${tests}"/> + </javac> + + <copy todir="${testclasses}"> + <!-- copy any non java src files into the build tree, e.g. log4j.properties --> + <fileset dir="${tests}"> + <exclude name="**/*.java"/> + <exclude name="**/package.html"/> + </fileset> + </copy> + </target> + + <!-- Build jar archive --> + <target name="jar" depends="compiletests"> + <mkdir dir="${dist}"/> + <jar basedir="${classes}" jarfile="${dist}/apache-management-common.jar"/> + <jar basedir="${testclasses}" jarfile="${dist}/apache-management-tests.jar"/> + </target> + + + <target name="javadoc" depends="compile, compiletests"> + <mkdir dir="${dist}/docs/api"/> + <javadoc sourcepath="${src}" destdir="${dist}/docs/api" + packagenames="org.apache.qpid.*" classpathref="apache.classpath" author="true" + version="true" windowTitle="AMQP Client API" doctitle="AMQP Client API" + footer="See <a href="http://www.apache.org">www.apache.org</a> for more information." + use="true" verbose="false"/> + </target> + + <target name="ServiceProvidingClient" depends="compiletests"> + <java fork="yes" classname="org.apache.qpid.requestreply1.ServiceProvidingClient"> + <classpath refid="apache.classpath"/> + <jvmarg value="-server"/> + <jvmarg value="-Damqj.logging.level=INFO"/> + <arg value="localhost"/> + <arg value="5672"/> + <arg value="guest"/> + <arg value="guest"/> + <arg value="/vpath"/> + <arg value="serviceQ1"/> + </java> + </target> + + <target name="ServiceRequestingClient" depends="compiletests"> + <java fork="yes" classname="org.apache.qpid.requestreply1.ServiceRequestingClient"> + <classpath refid="apache.classpath"/> + <jvmarg value="-server"/> + <jvmarg value="-Damqj.logging.level=INFO"/> + <arg value="localhost"/> + <arg value="5672"/> + <arg value="guest"/> + <arg value="guest"/> + <arg value="/vpath"/> + <arg value="serviceQ1"/> + <arg value="5000"/> + </java> + </target> + + <target name="profile" depends="compile" description="Profile Project"> + <fail unless="netbeans.home">This target can only run inside the NetBeans IDE.</fail> + <nbprofiledirect> + <classpath refid="apache.classpath"/> + </nbprofiledirect> + <java fork="true" classname="org.apache.qpid.requestreply1.ServiceRequestingClient" + dir="${profiler.session.working.dir}" + jvm="${profiler.info.jvm}"> + <jvmarg value="${profiler.info.jvmargs.agent}"/> + <jvmarg line="${profiler.info.jvmargs}"/> + <env key="Path" path="${profiler.info.agentpath}:${env.Path}"/> + <classpath refid="apache.classpath"/> + <jvmarg value="-server"/> + <jvmarg value="-Damqj.logging.level=INFO"/> + <arg value="localhost"/> + <arg value="5672"/> + <arg value="guest"/> + <arg value="guest"/> + <arg value="/vpath"/> + <arg value="serviceQ1"/> + <arg value="5000"/> + </java> + </target> + + <target name="profile-single" depends="compile" description="Profile File"> + <fail unless="netbeans.home">This target can only run inside the NetBeans IDE.</fail> + <nbprofile classname="${profile.class}"> + <classpath refid="apache.classpath"/> + </nbprofile> + </target> +</project> diff --git a/java/management/core/etc/cml-exampleschema.xml b/java/management/core/etc/cml-exampleschema.xml new file mode 100644 index 0000000000..bcee38246f --- /dev/null +++ b/java/management/core/etc/cml-exampleschema.xml @@ -0,0 +1,51 @@ +<?xml version="1.0"?> +<!-- + - + - Copyright (c) 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. + - + --> +<cml xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://www.apache.org/schema/cml cml.xsd" + xmlns="http://www.apache.org/schema/cml" + version="1.0"> + <schema-reply name = "qpid.apache.org/kernel" version = "0.1" status = "ok"> + <class name = "broker"> + <field name = "started" label = "Date, time broker started" /> + <field name = "vhost" type = "objref" repeat = "1" /> + </class> + <class name = "vhost"> + <field name = "name" label = "Virtual host path" /> + <field name = "exchange" type = "objref" repeat = "1" /> + <field name = "queue" type = "objref" repeat = "1" /> + </class> + <class name = "exchange"> + <field name = "name" /> + <field name = "type" /> + <field name = "durable" label = "Durable exchange?" type = "bool" /> + <field name = "auto_delete" label = "Auto-deleted?" type = "bool" /> + <field name = "bindings" label = "Number of bindings" type = "int" /> + </class> + <class name = "queue"> + <field name = "scope" /> + <field name = "name" /> + <field name = "enabled" label = "Queue accepts new messages?" modify = "1" /> + <field name = "durable" label = "Durable queue?" type = "bool" /> + <field name = "exclusive" label = "Exclusive to one connection?" type = "bool" /> + <field name = "auto_delete" label = "Auto-deleted?" type = "bool" /> + <field name = "consumers" label = "Number of consumers" type = "int" /> + <field name = "messages" label = "Number of messages" type = "int" /> + </class> + </schema-reply> +</cml> diff --git a/java/management/core/etc/cml.xsd b/java/management/core/etc/cml.xsd new file mode 100644 index 0000000000..99c21b41f9 --- /dev/null +++ b/java/management/core/etc/cml.xsd @@ -0,0 +1,175 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + - + - Copyright (c) 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. + - + --> +<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.apache.org/qpid/schema/cml" xmlns="http://www.apache.org/qpid/schema/cml" + elementFormDefault="qualified"> + <xs:element name="cml"> + <xs:annotation> + <xs:documentation>Defines a CML document as a schema or a...</xs:documentation> + </xs:annotation> + <xs:complexType> + <xs:choice> + <xs:element name="schema-request" minOccurs="0"/> + <xs:element name="schema-reply" type="schema-reply-type" minOccurs="0" > + <!--<xs:key name="classkey"> + <xs:selector xpath="class"/> + <xs:field xpath="@name"/> + </xs:key>--> + </xs:element> + <xs:element name="inspect-request" type="inspect-request-type" minOccurs="0"/> + <xs:element name="inspect-reply" type="inspect-reply-type" minOccurs="0" /> + <xs:element name="method-request" type="method-request-type" minOccurs="0"/> + <xs:element name="method-reply" type="method-reply-type" minOccurs="0" /> + </xs:choice> + <xs:attribute name="version" type="xs:string" use="required"/> + </xs:complexType> + </xs:element> + <xs:complexType name="schema-reply-type"> + <xs:annotation> + <xs:documentation>Client request for a schema</xs:documentation> + </xs:annotation> + <xs:sequence> + <xs:element name="class" type="class-type" minOccurs="1" maxOccurs="unbounded"/> + </xs:sequence> + <xs:attribute name="name" type="xs:string" use="required"/> + <xs:attribute name="version" type="xs:string" use="required"/> + <xs:attribute name="status"> + <xs:simpleType> + <xs:restriction base="xs:string"> + <xs:enumeration value="ok"/> + <xs:enumeration value="not ok"/> + </xs:restriction> + </xs:simpleType> + </xs:attribute> + </xs:complexType> + <xs:complexType name="class-type"> + <xs:annotation> + <xs:documentation>Defines a class which is a managable object</xs:documentation> + </xs:annotation> + <xs:choice> + <xs:element name="field" type="field-type" minOccurs="0" maxOccurs="unbounded"> + <xs:unique name="uniqueFieldName"> + <xs:selector xpath="field"/> + <xs:field xpath="@name"/> + </xs:unique> + </xs:element> + <xs:element name="method" type="method-type" minOccurs="0" maxOccurs="unbounded"> + <xs:unique name="uniqueMethodName"> + <xs:selector xpath="method"/> + <xs:field xpath="@name"/> + </xs:unique> + </xs:element> + </xs:choice> + <xs:attribute name="name" type="xs:string" use="required"/> + </xs:complexType> + <xs:complexType name="field-type"> + <xs:annotation> + <xs:documentation>Defines a field within a class</xs:documentation> + </xs:annotation> + <xs:simpleContent> + <xs:extension base="xs:string"> + <xs:attribute name="name" type="xs:string" use="required"/> + <xs:attribute name="type" use="optional" default="string"> + <xs:simpleType> + <xs:restriction base="xs:string"> + <xs:enumeration value="bool"/> + <xs:enumeration value="string"/> + <xs:enumeration value="int"/> + <xs:enumeration value="objref"/> + <xs:enumeration value="time"/> + </xs:restriction> + </xs:simpleType> + </xs:attribute> + <xs:attribute name="label" type="xs:string" use="optional"/> + <xs:attribute name="repeat" type="xs:boolean" use="optional" default="false"/> + <xs:attribute name="modify" type="xs:boolean" use="optional" default="false"/> + </xs:extension> + </xs:simpleContent> + </xs:complexType> + <xs:complexType name="method-type"> + <xs:annotation> + <xs:documentation>Defines a method within a class</xs:documentation> + </xs:annotation> + <xs:sequence> + <xs:element name="field" type="field-type" minOccurs="0" maxOccurs="unbounded"> + <xs:unique name="uniqueArgumentName"> + <xs:selector xpath="field"/> + <xs:field xpath="@name"/> + </xs:unique> + </xs:element> + </xs:sequence> + <xs:attribute name="name" type="xs:string" use="required"/> + </xs:complexType> + <xs:complexType name="inspect-request-type"> + <xs:annotation> + <xs:documentation>A request to get the property values of an instance</xs:documentation> + </xs:annotation> + <xs:attribute name="object" type="xs:int" use="required"/> + </xs:complexType> + <xs:complexType name="inspect-reply-type"> + <xs:annotation> + <xs:documentation>A response containing the properties of an instance</xs:documentation> + </xs:annotation> + <xs:sequence> + <xs:element name="field" type="field-type" minOccurs="0" maxOccurs="unbounded"/> + <xs:element name="object" type="object-type" minOccurs="0" maxOccurs="unbounded"/> + </xs:sequence> + <xs:attribute name="class" type="xs:string" use="optional"/> + <xs:attribute name="status" use="optional"> + <xs:simpleType> + <xs:restriction base="xs:string"> + <xs:enumeration value="ok"/> + <xs:enumeration value="notfound"/> + <xs:enumeration value="noaccess"/> + <xs:enumeration value="invalid"/> + </xs:restriction> + </xs:simpleType> + </xs:attribute> + <xs:attribute name="object" type="xs:int" use="required"/> + </xs:complexType> + <xs:complexType name="object-type"> + <xs:annotation> + <xs:documentation>A reference to an object instance</xs:documentation> + </xs:annotation> + <xs:attribute name="class" type="xs:string" use="required"/> + <xs:attribute name="id" type="xs:int" use="required"/> + </xs:complexType> + <xs:complexType name="method-request-type"> + <xs:annotation> + <xs:documentation>A request to invoke a method</xs:documentation> + </xs:annotation> + <xs:attribute name="object" type="xs:int" use="required"/> + <xs:attribute name="name" type="xs:string" use="required"/> + </xs:complexType> + <xs:complexType name="method-reply-type"> + <xs:annotation> + <xs:documentation>A reply to a method invocation request</xs:documentation> + </xs:annotation> + <xs:attribute name="object" type="xs:int" use="required"/> + <xs:attribute name="status" use="required"> + <xs:simpleType> + <xs:restriction base="xs:string"> + <xs:enumeration value="ok"/> + <xs:enumeration value="notfound"/> + <xs:enumeration value="noaccess"/> + <xs:enumeration value="invalid"/> + </xs:restriction> + </xs:simpleType> + </xs:attribute> + </xs:complexType> +</xs:schema> diff --git a/java/management/core/lib/jakarta-commons/commons-attributes-api.jar b/java/management/core/lib/jakarta-commons/commons-attributes-api.jar Binary files differnew file mode 100644 index 0000000000..b41cd055bb --- /dev/null +++ b/java/management/core/lib/jakarta-commons/commons-attributes-api.jar diff --git a/java/management/core/lib/jakarta-commons/commons-attributes-compiler.jar b/java/management/core/lib/jakarta-commons/commons-attributes-compiler.jar Binary files differnew file mode 100644 index 0000000000..ffd93f79eb --- /dev/null +++ b/java/management/core/lib/jakarta-commons/commons-attributes-compiler.jar diff --git a/java/management/core/lib/jakarta-commons/commons-beanutils.jar b/java/management/core/lib/jakarta-commons/commons-beanutils.jar Binary files differnew file mode 100644 index 0000000000..b1b89c9c92 --- /dev/null +++ b/java/management/core/lib/jakarta-commons/commons-beanutils.jar diff --git a/java/management/core/lib/jakarta-commons/commons-codec.jar b/java/management/core/lib/jakarta-commons/commons-codec.jar Binary files differnew file mode 100644 index 0000000000..957b6752af --- /dev/null +++ b/java/management/core/lib/jakarta-commons/commons-codec.jar diff --git a/java/management/core/lib/jakarta-commons/commons-collections.jar b/java/management/core/lib/jakarta-commons/commons-collections.jar Binary files differnew file mode 100644 index 0000000000..41e230feea --- /dev/null +++ b/java/management/core/lib/jakarta-commons/commons-collections.jar diff --git a/java/management/core/lib/jakarta-commons/commons-dbcp.jar b/java/management/core/lib/jakarta-commons/commons-dbcp.jar Binary files differnew file mode 100644 index 0000000000..08440c02e5 --- /dev/null +++ b/java/management/core/lib/jakarta-commons/commons-dbcp.jar diff --git a/java/management/core/lib/jakarta-commons/commons-digester.jar b/java/management/core/lib/jakarta-commons/commons-digester.jar Binary files differnew file mode 100644 index 0000000000..9765493306 --- /dev/null +++ b/java/management/core/lib/jakarta-commons/commons-digester.jar diff --git a/java/management/core/lib/jakarta-commons/commons-discovery.jar b/java/management/core/lib/jakarta-commons/commons-discovery.jar Binary files differnew file mode 100644 index 0000000000..eff4db19ef --- /dev/null +++ b/java/management/core/lib/jakarta-commons/commons-discovery.jar diff --git a/java/management/core/lib/jakarta-commons/commons-fileupload.jar b/java/management/core/lib/jakarta-commons/commons-fileupload.jar Binary files differnew file mode 100644 index 0000000000..1ca4a9cd31 --- /dev/null +++ b/java/management/core/lib/jakarta-commons/commons-fileupload.jar diff --git a/java/management/core/lib/jakarta-commons/commons-httpclient.jar b/java/management/core/lib/jakarta-commons/commons-httpclient.jar Binary files differnew file mode 100644 index 0000000000..c17584060d --- /dev/null +++ b/java/management/core/lib/jakarta-commons/commons-httpclient.jar diff --git a/java/management/core/lib/jakarta-commons/commons-lang.jar b/java/management/core/lib/jakarta-commons/commons-lang.jar Binary files differnew file mode 100644 index 0000000000..87b80ab5db --- /dev/null +++ b/java/management/core/lib/jakarta-commons/commons-lang.jar diff --git a/java/management/core/lib/jakarta-commons/commons-logging.jar b/java/management/core/lib/jakarta-commons/commons-logging.jar Binary files differnew file mode 100644 index 0000000000..b73a80fab6 --- /dev/null +++ b/java/management/core/lib/jakarta-commons/commons-logging.jar diff --git a/java/management/core/lib/jakarta-commons/commons-pool.jar b/java/management/core/lib/jakarta-commons/commons-pool.jar Binary files differnew file mode 100644 index 0000000000..4ba534c90e --- /dev/null +++ b/java/management/core/lib/jakarta-commons/commons-pool.jar diff --git a/java/management/core/lib/jakarta-commons/commons-validator.jar b/java/management/core/lib/jakarta-commons/commons-validator.jar Binary files differnew file mode 100644 index 0000000000..bf76e86c29 --- /dev/null +++ b/java/management/core/lib/jakarta-commons/commons-validator.jar diff --git a/java/management/core/lib/log4j/log4j-1.2.9.jar b/java/management/core/lib/log4j/log4j-1.2.9.jar Binary files differnew file mode 100644 index 0000000000..a6568b01a2 --- /dev/null +++ b/java/management/core/lib/log4j/log4j-1.2.9.jar diff --git a/java/management/core/lib/spring/spring-beans.dtd b/java/management/core/lib/spring/spring-beans.dtd new file mode 100644 index 0000000000..050f845788 --- /dev/null +++ b/java/management/core/lib/spring/spring-beans.dtd @@ -0,0 +1,587 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<!-- + Spring XML Beans DTD + Authors: Rod Johnson, Juergen Hoeller, Alef Arendsen, Colin Sampaleanu + + This defines a simple and consistent way of creating a namespace + of JavaBeans objects, managed by a Spring BeanFactory, read by + XmlBeanDefinitionReader (with DefaultXmlBeanDefinitionParser). + + This document type is used by most Spring functionality, including + web application contexts, which are based on bean factories. + + Each "bean" element in this document defines a JavaBean. + Typically the bean class is specified, along with JavaBean properties + and/or constructor arguments. + + Bean instances can be "singletons" (shared instances) or "prototypes" + (independent instances). Further scopes are supposed to be built on top + of the core BeanFactory infrastructure and are therefore not part of it. + + References among beans are supported, i.e. setting a JavaBean property + or a constructor argument to refer to another bean in the same factory + (or an ancestor factory). + + As alternative to bean references, "inner bean definitions" can be used. + Singleton flags of such inner bean definitions are effectively ignored: + Inner beans are typically anonymous prototypes. + + There is also support for lists, sets, maps, and java.util.Properties + as bean property types or constructor argument types. + + As the format is simple, a DTD is sufficient, and there's no need + for a schema at this point. + + XML documents that conform to this DTD should declare the following doctype: + + <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" + "http://www.springframework.org/dtd/spring-beans.dtd"> +--> + + +<!-- + The document root. A document can contain bean definitions only, + imports only, or a mixture of both (typically with imports first). +--> +<!ELEMENT beans ( + description?, + (import | alias | bean)* +)> + +<!-- + Default values for all bean definitions. Can be overridden at + the "bean" level. See those attribute definitions for details. +--> +<!ATTLIST beans default-lazy-init (true | false) "false"> +<!ATTLIST beans default-autowire (no | byName | byType | constructor | autodetect) "no"> +<!ATTLIST beans default-dependency-check (none | objects | simple | all) "none"> + +<!-- + Element containing informative text describing the purpose of the enclosing + element. Always optional. + Used primarily for user documentation of XML bean definition documents. +--> +<!ELEMENT description (#PCDATA)> + + +<!-- + Specifies an XML bean definition resource to import. +--> +<!ELEMENT import EMPTY> + +<!-- + The relative resource location of the XML bean definition file to import, + for example "myImport.xml" or "includes/myImport.xml" or "../myImport.xml". +--> +<!ATTLIST import resource CDATA #REQUIRED> + + +<!-- + Defines an alias for a bean, which can reside in a different definition file. +--> +<!ELEMENT alias EMPTY> + +<!-- + The name of the bean to define an alias for. +--> +<!ATTLIST alias name CDATA #REQUIRED> + +<!-- + The alias name to define for the bean. +--> +<!ATTLIST alias alias CDATA #REQUIRED> + + +<!-- + Defines a single (usually named) bean. + + A bean definition may contain nested tags for constructor arguments, + property values, lookup methods, and replaced methods. Mixing constructor + injection and setter injection on the same bean is explicitly supported. +--> +<!ELEMENT bean ( + description?, + (constructor-arg | property | lookup-method | replaced-method)* +)> + +<!-- + Beans can be identified by an id, to enable reference checking. + + There are constraints on a valid XML id: if you want to reference your bean + in Java code using a name that's illegal as an XML id, use the optional + "name" attribute. If neither is given, the bean class name is used as id + (with an appended counter like "#2" if there is already a bean with that name). +--> +<!ATTLIST bean id ID #IMPLIED> + +<!-- + Optional. Can be used to create one or more aliases illegal in an id. + Multiple aliases can be separated by any number of spaces or commas. +--> +<!ATTLIST bean name CDATA #IMPLIED> + +<!-- + Each bean definition must specify the fully qualified name of the class, + except if it pure serves as parent for child bean definitions. +--> +<!ATTLIST bean class CDATA #IMPLIED> + +<!-- + Optionally specify a parent bean definition. + + Will use the bean class of the parent if none specified, but can + also override it. In the latter case, the child bean class must be + compatible with the parent, i.e. accept the parent's property values + and constructor argument values, if any. + + A child bean definition will inherit constructor argument values, + property values and method overrides from the parent, with the option + to add new values. If init method, destroy method, factory bean and/or factory + method are specified, they will override the corresponding parent settings. + + The remaining settings will always be taken from the child definition: + depends on, autowire mode, dependency check, singleton, lazy init. +--> +<!ATTLIST bean parent CDATA #IMPLIED> + +<!-- + Is this bean "abstract", i.e. not meant to be instantiated itself but + rather just serving as parent for concrete child bean definitions. + Default is "false". Specify "true" to tell the bean factory to not try to + instantiate that particular bean in any case. +--> +<!ATTLIST bean abstract (true | false) "false"> + +<!-- + Is this bean a "singleton" (one shared instance, which will + be returned by all calls to getBean() with the id), + or a "prototype" (independent instance resulting from each call to + getBean(). Default is singleton. + + Singletons are most commonly used, and are ideal for multi-threaded + service objects. +--> +<!ATTLIST bean singleton (true | false) "true"> + +<!-- + If this bean should be lazily initialized. + If false, it will get instantiated on startup by bean factories + that perform eager initialization of singletons. +--> +<!ATTLIST bean lazy-init (true | false | default) "default"> + +<!-- + Optional attribute controlling whether to "autowire" bean properties. + This is an automagical process in which bean references don't need to be coded + explicitly in the XML bean definition file, but Spring works out dependencies. + + There are 5 modes: + + 1. "no" + The traditional Spring default. No automagical wiring. Bean references + must be defined in the XML file via the <ref> element. We recommend this + in most cases as it makes documentation more explicit. + + 2. "byName" + Autowiring by property name. If a bean of class Cat exposes a dog property, + Spring will try to set this to the value of the bean "dog" in the current factory. + If there is no matching bean by name, nothing special happens; + use dependency-check="objects" to raise an error in that case. + + 3. "byType" + Autowiring if there is exactly one bean of the property type in the bean factory. + If there is more than one, a fatal error is raised, and you can't use byType + autowiring for that bean. If there is none, nothing special happens; + use dependency-check="objects" to raise an error in that case. + + 4. "constructor" + Analogous to "byType" for constructor arguments. If there isn't exactly one bean + of the constructor argument type in the bean factory, a fatal error is raised. + + 5. "autodetect" + Chooses "constructor" or "byType" through introspection of the bean class. + If a default constructor is found, "byType" gets applied. + + The latter two are similar to PicoContainer and make bean factories simple to + configure for small namespaces, but doesn't work as well as standard Spring + behaviour for bigger applications. + + Note that explicit dependencies, i.e. "property" and "constructor-arg" elements, + always override autowiring. Autowire behaviour can be combined with dependency + checking, which will be performed after all autowiring has been completed. +--> +<!ATTLIST bean autowire (no | byName | byType | constructor | autodetect | default) "default"> + +<!-- + Optional attribute controlling whether to check whether all this + beans dependencies, expressed in its properties, are satisfied. + Default is no dependency checking. + + "simple" type dependency checking includes primitives and String + "object" includes collaborators (other beans in the factory) + "all" includes both types of dependency checking +--> +<!ATTLIST bean dependency-check (none | objects | simple | all | default) "default"> + +<!-- + The names of the beans that this bean depends on being initialized. + The bean factory will guarantee that these beans get initialized before. + + Note that dependencies are normally expressed through bean properties or + constructor arguments. This property should just be necessary for other kinds + of dependencies like statics (*ugh*) or database preparation on startup. +--> +<!ATTLIST bean depends-on CDATA #IMPLIED> + +<!-- + Optional attribute for the name of the custom initialization method + to invoke after setting bean properties. The method must have no arguments, + but may throw any exception. +--> +<!ATTLIST bean init-method CDATA #IMPLIED> + +<!-- + Optional attribute for the name of the custom destroy method to invoke + on bean factory shutdown. The method must have no arguments, + but may throw any exception. Note: Only invoked on singleton beans! +--> +<!ATTLIST bean destroy-method CDATA #IMPLIED> + +<!-- + Optional attribute specifying the name of a factory method to use to + create this object. Use constructor-arg elements to specify arguments + to the factory method, if it takes arguments. Autowiring does not apply + to factory methods. + + If the "class" attribute is present, the factory method will be a static + method on the class specified by the "class" attribute on this bean + definition. Often this will be the same class as that of the constructed + object - for example, when the factory method is used as an alternative + to a constructor. However, it may be on a different class. In that case, + the created object will *not* be of the class specified in the "class" + attribute. This is analogous to FactoryBean behavior. + + If the "factory-bean" attribute is present, the "class" attribute is not + used, and the factory method will be an instance method on the object + returned from a getBean call with the specified bean name. The factory + bean may be defined as a singleton or a prototype. + + The factory method can have any number of arguments. Autowiring is not + supported. Use indexed constructor-arg elements in conjunction with the + factory-method attribute. + + Setter Injection can be used in conjunction with a factory method. + Method Injection cannot, as the factory method returns an instance, + which will be used when the container creates the bean. +--> +<!ATTLIST bean factory-method CDATA #IMPLIED> + +<!-- + Alternative to class attribute for factory-method usage. + If this is specified, no class attribute should be used. + This should be set to the name of a bean in the current or + ancestor factories that contains the relevant factory method. + This allows the factory itself to be configured using Dependency + Injection, and an instance (rather than static) method to be used. +--> +<!ATTLIST bean factory-bean CDATA #IMPLIED> + + +<!-- + Bean definitions can specify zero or more constructor arguments. + This is an alternative to "autowire constructor". + Arguments correspond to either a specific index of the constructor argument + list or are supposed to be matched generically by type. + + Note: A single generic argument value will just be used once, rather than + potentially matched multiple times (as of Spring 1.1). + + constructor-arg elements are also used in conjunction with the factory-method + element to construct beans using static or instance factory methods. +--> +<!ELEMENT constructor-arg ( + description?, + (bean | ref | idref | value | null | list | set | map | props)? +)> + +<!-- + The constructor-arg tag can have an optional index attribute, + to specify the exact index in the constructor argument list. Only needed + to avoid ambiguities, e.g. in case of 2 arguments of the same type. +--> +<!ATTLIST constructor-arg index CDATA #IMPLIED> + +<!-- + The constructor-arg tag can have an optional type attribute, + to specify the exact type of the constructor argument. Only needed + to avoid ambiguities, e.g. in case of 2 single argument constructors + that can both be converted from a String. +--> +<!ATTLIST constructor-arg type CDATA #IMPLIED> + +<!-- + A short-cut alternative to a child element "ref bean=". +--> +<!ATTLIST constructor-arg ref CDATA #IMPLIED> + +<!-- + A short-cut alternative to a child element "value". +--> +<!ATTLIST constructor-arg value CDATA #IMPLIED> + + +<!-- + Bean definitions can have zero or more properties. + Property elements correspond to JavaBean setter methods exposed + by the bean classes. Spring supports primitives, references to other + beans in the same or related factories, lists, maps and properties. +--> +<!ELEMENT property ( + description?, + (bean | ref | idref | value | null | list | set | map | props)? +)> + +<!-- + The property name attribute is the name of the JavaBean property. + This follows JavaBean conventions: a name of "age" would correspond + to setAge()/optional getAge() methods. +--> +<!ATTLIST property name CDATA #REQUIRED> + +<!-- + A short-cut alternative to a child element "ref bean=". +--> +<!ATTLIST property ref CDATA #IMPLIED> + +<!-- + A short-cut alternative to a child element "value". +--> +<!ATTLIST property value CDATA #IMPLIED> + + +<!-- + A lookup method causes the IoC container to override the given method and return + the bean with the name given in the bean attribute. This is a form of Method Injection. + It's particularly useful as an alternative to implementing the BeanFactoryAware + interface, in order to be able to make getBean() calls for non-singleton instances + at runtime. In this case, Method Injection is a less invasive alternative. +--> +<!ELEMENT lookup-method EMPTY> + +<!-- + Name of a lookup method. This method should take no arguments. +--> +<!ATTLIST lookup-method name CDATA #IMPLIED> + +<!-- + Name of the bean in the current or ancestor factories that the lookup method + should resolve to. Often this bean will be a prototype, in which case the + lookup method will return a distinct instance on every invocation. This + is useful for single-threaded objects. +--> +<!ATTLIST lookup-method bean CDATA #IMPLIED> + + +<!-- + Similar to the lookup method mechanism, the replaced-method element is used to control + IoC container method overriding: Method Injection. This mechanism allows the overriding + of a method with arbitrary code. +--> +<!ELEMENT replaced-method ( + (arg-type)* +)> + +<!-- + Name of the method whose implementation should be replaced by the IoC container. + If this method is not overloaded, there's no need to use arg-type subelements. + If this method is overloaded, arg-type subelements must be used for all + override definitions for the method. +--> +<!ATTLIST replaced-method name CDATA #IMPLIED> + +<!-- + Bean name of an implementation of the MethodReplacer interface + in the current or ancestor factories. This may be a singleton or prototype + bean. If it's a prototype, a new instance will be used for each method replacement. + Singleton usage is the norm. +--> +<!ATTLIST replaced-method replacer CDATA #IMPLIED> + +<!-- + Subelement of replaced-method identifying an argument for a replaced method + in the event of method overloading. +--> +<!ELEMENT arg-type (#PCDATA)> + +<!-- + Specification of the type of an overloaded method argument as a String. + For convenience, this may be a substring of the FQN. E.g. all the + following would match "java.lang.String": + - java.lang.String + - String + - Str + + As the number of arguments will be checked also, this convenience can often + be used to save typing. +--> +<!ATTLIST arg-type match CDATA #IMPLIED> + + +<!-- + Defines a reference to another bean in this factory or an external + factory (parent or included factory). +--> +<!ELEMENT ref EMPTY> + +<!-- + References must specify a name of the target bean. + The "bean" attribute can reference any name from any bean in the context, + to be checked at runtime. + Local references, using the "local" attribute, have to use bean ids; + they can be checked by this DTD, thus should be preferred for references + within the same bean factory XML file. +--> +<!ATTLIST ref bean CDATA #IMPLIED> +<!ATTLIST ref local IDREF #IMPLIED> +<!ATTLIST ref parent CDATA #IMPLIED> + + +<!-- + Defines a string property value, which must also be the id of another + bean in this factory or an external factory (parent or included factory). + While a regular 'value' element could instead be used for the same effect, + using idref in this case allows validation of local bean ids by the xml + parser, and name completion by helper tools. +--> +<!ELEMENT idref EMPTY> + +<!-- + ID refs must specify a name of the target bean. + The "bean" attribute can reference any name from any bean in the context, + potentially to be checked at runtime by bean factory implementations. + Local references, using the "local" attribute, have to use bean ids; + they can be checked by this DTD, thus should be preferred for references + within the same bean factory XML file. +--> +<!ATTLIST idref bean CDATA #IMPLIED> +<!ATTLIST idref local IDREF #IMPLIED> + + +<!-- + Contains a string representation of a property value. + The property may be a string, or may be converted to the + required type using the JavaBeans PropertyEditor + machinery. This makes it possible for application developers + to write custom PropertyEditor implementations that can + convert strings to objects. + + Note that this is recommended for simple objects only. + Configure more complex objects by populating JavaBean + properties with references to other beans. +--> +<!ELEMENT value (#PCDATA)> + +<!-- + The value tag can have an optional type attribute, to specify the + exact type that the value should be converted to. Only needed + if the type of the target property or constructor argument is + too generic: for example, in case of a collection element. +--> +<!ATTLIST value type CDATA #IMPLIED> + +<!-- + Denotes a Java null value. Necessary because an empty "value" tag + will resolve to an empty String, which will not be resolved to a + null value unless a special PropertyEditor does so. +--> +<!ELEMENT null (#PCDATA)> + + +<!-- + A list can contain multiple inner bean, ref, collection, or value elements. + Java lists are untyped, pending generics support in Java 1.5, + although references will be strongly typed. + A list can also map to an array type. The necessary conversion + is automatically performed by the BeanFactory. +--> +<!ELEMENT list ( + (bean | ref | idref | value | null | list | set | map | props)* +)> + +<!-- + A set can contain multiple inner bean, ref, collection, or value elements. + Java sets are untyped, pending generics support in Java 1.5, + although references will be strongly typed. +--> +<!ELEMENT set ( + (bean | ref | idref | value | null | list | set | map | props)* +)> + + +<!-- + A Spring map is a mapping from a string key to object. + Maps may be empty. +--> +<!ELEMENT map ( + (entry)* +)> + +<!-- + A map entry can be an inner bean, ref, value, or collection. + The key of the entry is given by the "key" attribute or child element. +--> +<!ELEMENT entry ( + key?, + (bean | ref | idref | value | null | list | set | map | props)? +)> + +<!-- + Each map element must specify its key as attribute or as child element. + A key attribute is always a String value. +--> +<!ATTLIST entry key CDATA #IMPLIED> + +<!-- + A short-cut alternative to a "key" element with a "ref bean=" child element. +--> +<!ATTLIST entry key-ref CDATA #IMPLIED> + +<!-- + A short-cut alternative to a child element "value". +--> +<!ATTLIST entry value CDATA #IMPLIED> + +<!-- + A short-cut alternative to a child element "ref bean=". +--> +<!ATTLIST entry value-ref CDATA #IMPLIED> + +<!-- + A key element can contain an inner bean, ref, value, or collection. +--> +<!ELEMENT key ( + (bean | ref | idref | value | null | list | set | map | props) +)> + + +<!-- + Props elements differ from map elements in that values must be strings. + Props may be empty. +--> +<!ELEMENT props ( + (prop)* +)> + +<!-- + Element content is the string value of the property. + Note that whitespace is trimmed off to avoid unwanted whitespace + caused by typical XML formatting. +--> +<!ELEMENT prop (#PCDATA)> + +<!-- + Each property element must specify its key. +--> +<!ATTLIST prop key CDATA #REQUIRED> + diff --git a/java/management/core/lib/spring/spring.ftl b/java/management/core/lib/spring/spring.ftl new file mode 100644 index 0000000000..45d8ad0b39 --- /dev/null +++ b/java/management/core/lib/spring/spring.ftl @@ -0,0 +1,316 @@ +<#-- + * spring.ftl + * + * This file consists of a collection of FreeMarker macros aimed at easing + * some of the common requirements of web applications - in particular + * handling of forms. + * + * Spring's FreeMarker support will automatically make this file and therefore + * all macros within it available to any application using Spring's + * FreeMarkerConfigurer. + * + * To take advantage of these macros, the "exposeSpringMacroHelpers" property + * of the FreeMarker class needs to be set to "true". This will expose a + * RequestContext under the name "springMacroRequestContext", as needed by + * the macros in this library. + * + * @author Darren Davison + * @author Juergen Hoeller + * @since 1.1 + --> + +<#-- + * message + * + * Macro to translate a message code into a message. + --> +<#macro message code>${springMacroRequestContext.getMessage(code)}</#macro> + +<#-- + * messageText + * + * Macro to translate a message code into a message, + * using the given default text if no message found. + --> +<#macro messageText code, text>${springMacroRequestContext.getMessage(code, text)}</#macro> + +<#-- + * url + * + * Takes a relative URL and makes it absolute from the server root by + * adding the context root for the web application. + --> +<#macro url relativeUrl>${springMacroRequestContext.getContextPath()}${relativeUrl}</#macro> + +<#-- + * bind + * + * Exposes a BindStatus object for the given bind path, which can be + * a bean (e.g. "person") to get global errors, or a bean property + * (e.g. "person.name") to get field errors. Can be called multiple times + * within a form to bind to multiple command objects and/or field names. + * + * This macro will participate in the default HTML escape setting for the given + * RequestContext. This can be customized by calling "setDefaultHtmlEscape" + * on the "springMacroRequestContext" context variable, or via the + * "defaultHtmlEscape" context-param in web.xml (same as for the JSP bind tag). + * Also regards a "htmlEscape" variable in the namespace of this library. + * + * Producing no output, the following context variable will be available + * each time this macro is referenced (assuming you import this library in + * your templates with the namespace 'spring'): + * + * spring.status : a BindStatus instance holding the command object name, + * expression, value, and error messages and codes for the path supplied + * + * @param path : the path (string value) of the value required to bind to. + * Spring defaults to a command name of "command" but this can be overridden + * by user config. + --> +<#macro bind path> + <#if htmlEscape?exists> + <#assign status = springMacroRequestContext.getBindStatus(path, htmlEscape)> + <#else> + <#assign status = springMacroRequestContext.getBindStatus(path)> + </#if> + <#-- assign a temporary value, forcing a string representation for any + kind of variable. This temp value is only used in this macro lib --> + <#if status.value?exists && status.value?is_boolean> + <#assign stringStatusValue=status.value?string> + <#else> + <#assign stringStatusValue=status.value?default("")> + </#if> +</#macro> + +<#-- + * bindEscaped + * + * Similar to spring:bind, but takes an explicit HTML escape flag rather + * than relying on the default HTML escape setting. + --> +<#macro bindEscaped path, htmlEscape> + <#assign status = springMacroRequestContext.getBindStatus(path, htmlEscape)> + <#-- assign a temporary value, forcing a string representation for any + kind of variable. This temp value is only used in this macro lib --> + <#if status.value?exists && status.value?is_boolean> + <#assign stringStatusValue=status.value?string> + <#else> + <#assign stringStatusValue=status.value?default("")> + </#if> +</#macro> + +<#-- + * formInput + * + * Display a form input field of type 'text' and bind it to an attribute + * of a command or bean. + * + * @param path the name of the field to bind to + * @param attributes any additional attributes for the element (such as class + * or CSS styles or size + --> +<#macro formInput path attributes="" fieldType="text" > + <@bind path/> + <input type="${fieldType}" name="${status.expression}" value="<#if fieldType!="password">${stringStatusValue}</#if>" ${attributes} + <@closeTag/> +</#macro> + +<#-- + * formPasswordInput + * + * Display a form input field of type 'password' and bind it to an attribute + * of a command or bean. No value will ever be displayed. This functionality + * can also be obtained by calling the formInput macro with a 'type' parameter + * of 'password' + * + * @param path the name of the field to bind to + * @param attributes any additional attributes for the element (such as class + * or CSS styles or size + --> +<#macro formPasswordInput path attributes="" > + <@formInput path, attributes, "password"/> +</#macro> + +<#-- + * formHiddenInput + * + * Generate a form input field of type 'hidden' and bind it to an attribute + * of a command or bean. This functionality can also be obtained by calling + * the formInput macro with a 'type' parameter of 'hidden' + * + * @param path the name of the field to bind to + * @param attributes any additional attributes for the element (such as class + * or CSS styles or size + --> +<#macro formHiddenInput path attributes="" > + <@formInput path, attributes, "hidden"/> +</#macro> + +<#-- + * formTextarea + * + * Display a text area and bind it to an attribute of a command or bean. + * + * @param path the name of the field to bind to + * @param attributes any additional attributes for the element (such as class + * or CSS styles or size + --> +<#macro formTextarea path attributes="" > + <@bind path/> + <textarea name="${status.expression}" ${attributes}>${stringStatusValue}</textarea> +</#macro> + +<#-- + * formSingleSelect + * + * Show a selectbox (dropdown) input element allowing a single value to be chosen + * from a list of options. + * + * @param path the name of the field to bind to + * @param options a map (value=label) of all the available options + * @param attributes any additional attributes for the element (such as class + * or CSS styles or size +--> +<#macro formSingleSelect path options attributes=""> + <@bind path/> + <select name="${status.expression}" ${attributes}> + <#list options?keys as value> + <option value="${value}"<@checkSelected value/>>${options[value]}</option> + </#list> + </select> +</#macro> + +<#-- + * formMultiSelect + * + * Show a listbox of options allowing the user to make 0 or more choices from + * the list of options. + * + * @param path the name of the field to bind to + * @param options a map (value=label) of all the available options + * @param attributes any additional attributes for the element (such as class + * or CSS styles or size +--> +<#macro formMultiSelect path options attributes=""> + <@bind path/> + <select multiple="multiple" name="${status.expression}" ${attributes}> + <#list options?keys as value> + <#assign isSelected = contains(status.value?default([""]), value)> + <option value="${value}" <#if isSelected>selected="selected"</#if>>${options[value]}</option> + </#list> + </select> +</#macro> + +<#-- + * formRadioButtons + * + * Show radio buttons. + * + * @param path the name of the field to bind to + * @param options a map (value=label) of all the available options + * @param separator the html tag or other character list that should be used to + * separate each option. Typically ' ' or '<br>' + * @param attributes any additional attributes for the element (such as class + * or CSS styles or size +--> +<#macro formRadioButtons path options separator attributes=""> + <@bind path/> + <#list options?keys as value> + <input type="radio" name="${status.expression}" value="${value}" + <#if stringStatusValue == value>checked="checked"</#if> ${attributes} + <@closeTag/> + ${options[value]}${separator} + </#list> +</#macro> + +<#-- + * formCheckboxes + * + * Show checkboxes. + * + * @param path the name of the field to bind to + * @param options a map (value=label) of all the available options + * @param separator the html tag or other character list that should be used to + * separate each option. Typically ' ' or '<br>' + * @param attributes any additional attributes for the element (such as class + * or CSS styles or size +--> +<#macro formCheckboxes path options separator attributes=""> + <@bind path/> + <#list options?keys as value> + <#assign isSelected = contains(status.value?default([""]), value)> + <input type="checkbox" name="${status.expression}" value="${value}" + <#if isSelected>checked="checked"</#if> ${attributes} + <@closeTag/> + ${options[value]}${separator} + </#list> +</#macro> + +<#-- + * showErrors + * + * Show validation errors for the currently bound field, with + * optional style attributes. + * + * @param separator the html tag or other character list that should be used to + * separate each option. Typically '<br>'. + * @param classOrStyle either the name of a CSS class element (which is defined in + * the template or an external CSS file) or an inline style. If the value passed in here + * contains a colon (:) then a 'style=' attribute will be used, else a 'class=' attribute + * will be used. +--> +<#macro showErrors separator classOrStyle=""> + <#list status.errorMessages as error> + <#if classOrStyle == ""> + <b>${error}</b> + <#else> + <#if classOrStyle?index_of(":") == -1><#assign attr="class"><#else><#assign attr="style"></#if> + <span ${attr}="${classOrStyle}">${error}</span> + </#if> + <#if error_has_next>${separator}</#if> + </#list> +</#macro> + +<#-- + * checkSelected + * + * Check a value in a list to see if it is the currently selected value. + * If so, add the 'selected="selected"' text to the output. + * Handles values of numeric and string types. + * This function is used internally but can be accessed by user code if required. + * + * @param value the current value in a list iteration +--> +<#macro checkSelected value> + <#if stringStatusValue?is_number && stringStatusValue == value?number>selected="selected"</#if> + <#if stringStatusValue?is_string && stringStatusValue == value>selected="selected"</#if> +</#macro> + +<#-- + * contains + * + * Macro to return true if the list contains the scalar, false if not. + * Surprisingly not a FreeMarker builtin. + * This function is used internally but can be accessed by user code if required. + * + * @param list the list to search for the item + * @param item the item to search for in the list + * @return true if item is found in the list, false otherwise +--> +<#function contains list item> + <#list list as nextInList> + <#if nextInList == item><#return true></#if> + </#list> + <#return false> +</#function> + +<#-- + * closeTag + * + * Simple macro to close an HTML tag that has no body with '>' or '/>', + * depending on the value of a 'xhtmlCompliant' variable in the namespace + * of this library. +--> +<#macro closeTag> + <#if xhtmlCompliant?exists && xhtmlCompliant>/><#else>></#if> +</#macro> diff --git a/java/management/core/lib/spring/spring.tld b/java/management/core/lib/spring/spring.tld new file mode 100644 index 0000000000..1bc7091f03 --- /dev/null +++ b/java/management/core/lib/spring/spring.tld @@ -0,0 +1,311 @@ +<?xml version="1.0" encoding="ISO-8859-1" ?> +<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd"> + +<taglib> + + <tlib-version>1.1.1</tlib-version> + + <jsp-version>1.2</jsp-version> + + <short-name>Spring</short-name> + + <uri>http://www.springframework.org/tags</uri> + + <description>Spring Framework JSP Tag Library. Authors: Rod Johnson, Juergen Hoeller</description> + + + <tag> + + <name>htmlEscape</name> + <tag-class>org.springframework.web.servlet.tags.HtmlEscapeTag</tag-class> + <body-content>JSP</body-content> + + <description> + Sets default HTML escape value for the current page. + Overrides a "defaultHtmlEscape" context-param in web.xml, if any. + </description> + + <attribute> + <name>defaultHtmlEscape</name> + <required>true</required> + <rtexprvalue>true</rtexprvalue> + </attribute> + + </tag> + + + <tag> + + <name>escapeBody</name> + <tag-class>org.springframework.web.servlet.tags.EscapeBodyTag</tag-class> + <body-content>JSP</body-content> + + <description> + Escapes its enclosed body content, applying HTML escaping and/or JavaScript escaping. + The HTML escaping flag participates in a page-wide or application-wide setting + (i.e. by HtmlEscapeTag or a "defaultHtmlEscape" context-param in web.xml). + </description> + + <attribute> + <name>htmlEscape</name> + <required>false</required> + <rtexprvalue>true</rtexprvalue> + </attribute> + + <attribute> + <name>javaScriptEscape</name> + <required>false</required> + <rtexprvalue>true</rtexprvalue> + </attribute> + + </tag> + + + <tag> + + <name>message</name> + <tag-class>org.springframework.web.servlet.tags.MessageTag</tag-class> + <body-content>JSP</body-content> + + <description> + Retrieves the message with the given code, or text if code isn't resolvable. + The HTML escaping flag participates in a page-wide or application-wide setting + (i.e. by HtmlEscapeTag or a "defaultHtmlEscape" context-param in web.xml). + </description> + + <attribute> + <name>code</name> + <required>false</required> + <rtexprvalue>true</rtexprvalue> + </attribute> + + <attribute> + <name>arguments</name> + <required>false</required> + <rtexprvalue>true</rtexprvalue> + </attribute> + + <attribute> + <name>text</name> + <required>false</required> + <rtexprvalue>true</rtexprvalue> + </attribute> + + <attribute> + <name>var</name> + <required>false</required> + <rtexprvalue>true</rtexprvalue> + </attribute> + + <attribute> + <name>scope</name> + <required>false</required> + <rtexprvalue>true</rtexprvalue> + </attribute> + + <attribute> + <name>htmlEscape</name> + <required>false</required> + <rtexprvalue>true</rtexprvalue> + </attribute> + + <attribute> + <name>javaScriptEscape</name> + <required>false</required> + <rtexprvalue>true</rtexprvalue> + </attribute> + + </tag> + + + <tag> + + <name>theme</name> + <tag-class>org.springframework.web.servlet.tags.ThemeTag</tag-class> + <body-content>JSP</body-content> + + <description> + Retrieves the theme message with the given code, or text if code isn't resolvable. + The HTML escaping flag participates in a page-wide or application-wide setting + (i.e. by HtmlEscapeTag or a "defaultHtmlEscape" context-param in web.xml). + </description> + + <attribute> + <name>code</name> + <required>false</required> + <rtexprvalue>true</rtexprvalue> + </attribute> + + <attribute> + <name>arguments</name> + <required>false</required> + <rtexprvalue>true</rtexprvalue> + </attribute> + + <attribute> + <name>text</name> + <required>false</required> + <rtexprvalue>true</rtexprvalue> + </attribute> + + <attribute> + <name>var</name> + <required>false</required> + <rtexprvalue>true</rtexprvalue> + </attribute> + + <attribute> + <name>scope</name> + <required>false</required> + <rtexprvalue>true</rtexprvalue> + </attribute> + + <attribute> + <name>htmlEscape</name> + <required>false</required> + <rtexprvalue>true</rtexprvalue> + </attribute> + + <attribute> + <name>javaScriptEscape</name> + <required>false</required> + <rtexprvalue>true</rtexprvalue> + </attribute> + + </tag> + + + <tag> + + <name>hasBindErrors</name> + <tag-class>org.springframework.web.servlet.tags.BindErrorsTag</tag-class> + <body-content>JSP</body-content> + + <description> + Provides Errors instance in case of bind errors. + The HTML escaping flag participates in a page-wide or application-wide setting + (i.e. by HtmlEscapeTag or a "defaultHtmlEscape" context-param in web.xml). + </description> + + <variable> + <name-given>errors</name-given> + <variable-class>org.springframework.validation.Errors</variable-class> + </variable> + + <attribute> + <name>name</name> + <required>true</required> + <rtexprvalue>true</rtexprvalue> + </attribute> + + <attribute> + <name>htmlEscape</name> + <required>false</required> + <rtexprvalue>true</rtexprvalue> + </attribute> + + </tag> + + + <tag> + + <name>nestedPath</name> + <tag-class>org.springframework.web.servlet.tags.NestedPathTag</tag-class> + <body-content>JSP</body-content> + + <description> + Sets a nested path to be used by the bind tag's path. + </description> + + <variable> + <name-given>nestedPath</name-given> + <variable-class>java.lang.String</variable-class> + </variable> + + <attribute> + <name>path</name> + <required>true</required> + <rtexprvalue>true</rtexprvalue> + </attribute> + + </tag> + + + <tag> + + <name>bind</name> + <tag-class>org.springframework.web.servlet.tags.BindTag</tag-class> + <body-content>JSP</body-content> + + <description> + Provides BindStatus object for the given bind path. + The HTML escaping flag participates in a page-wide or application-wide setting + (i.e. by HtmlEscapeTag or a "defaultHtmlEscape" context-param in web.xml). + </description> + + <variable> + <name-given>status</name-given> + <variable-class>org.springframework.web.servlet.support.BindStatus</variable-class> + </variable> + + <attribute> + <name>path</name> + <required>true</required> + <rtexprvalue>true</rtexprvalue> + </attribute> + + <attribute> + <name>ignoreNestedPath</name> + <required>false</required> + <rtexprvalue>true</rtexprvalue> + </attribute> + + <attribute> + <name>htmlEscape</name> + <required>false</required> + <rtexprvalue>true</rtexprvalue> + </attribute> + + </tag> + + + <tag> + + <name>transform</name> + <tag-class>org.springframework.web.servlet.tags.TransformTag</tag-class> + <body-content>JSP</body-content> + + <description> + Provides transformation of variables to Strings, using an appropriate + custom PropertyEditor from BindTag (can only be used inside BindTag). + The HTML escaping flag participates in a page-wide or application-wide setting + (i.e. by HtmlEscapeTag or a "defaultHtmlEscape" context-param in web.xml). + </description> + + <attribute> + <name>value</name> + <required>true</required> + <rtexprvalue>true</rtexprvalue> + </attribute> + + <attribute> + <name>var</name> + <required>false</required> + <rtexprvalue>true</rtexprvalue> + </attribute> + + <attribute> + <name>scope</name> + <required>false</required> + <rtexprvalue>true</rtexprvalue> + </attribute> + + <attribute> + <name>htmlEscape</name> + <required>false</required> + <rtexprvalue>true</rtexprvalue> + </attribute> + + </tag> + +</taglib> diff --git a/java/management/core/lib/spring/spring.vm b/java/management/core/lib/spring/spring.vm new file mode 100644 index 0000000000..50e104328c --- /dev/null +++ b/java/management/core/lib/spring/spring.vm @@ -0,0 +1,294 @@ +#** + * spring.vm + * + * This file consists of a collection of Velocity macros aimed at easing + * some of the common requirements of web applications - in particular + * handling of forms. + * + * Spring's Velocity support will automatically make this file and therefore + * all macros within it available to any application using Spring's + * VelocityConfigurer. + * + * To take advantage of these macros, the "exposeSpringMacroHelpers" property + * of the VelocityView class needs to be set to "true". This will expose a + * RequestContext under the name "springMacroRequestContext", as needed by + * the macros in this library. + * + * @author Darren Davison + * @author Juergen Hoeller + * @since 1.1 + *# + +#** + * springMessage + * + * Macro to translate a message code into a message. + *# +#macro( springMessage $code )$springMacroRequestContext.getMessage($code)#end + +#** + * springMessageText + * + * Macro to translate a message code into a message, + * using the given default text if no message found. + *# +#macro( springMessageText $code $text )$springMacroRequestContext.getMessage($code, $text)#end + +#** + * springUrl + * + * Takes a relative URL and makes it absolute from the server root by + * adding the context root for the web application. + *# +#macro( springUrl $relativeUrl )$springMacroRequestContext.getContextPath()${relativeUrl}#end + +#** + * springBind + * + * Exposes a BindStatus object for the given bind path, which can be + * a bean (e.g. "person") to get global errors, or a bean property + * (e.g. "person.name") to get field errors. Can be called multiple times + * within a form to bind to multiple command objects and/or field names. + * + * This macro will participate in the default HTML escape setting for the given + * RequestContext. This can be customized by calling "setDefaultHtmlEscape" + * on the "springMacroRequestContext" context variable, or via the + * "defaultHtmlEscape" context-param in web.xml (same as for the JSP bind tag). + * Also regards a "springHtmlEscape" variable in the template context. + * + * Producing no output, the following context variable will be available + * each time this macro is referenced: + * + * $status : a BindStatus instance holding the command object name, + * expression, value, and error codes and messages for the path supplied + * + * @param $path : the path (string value) of the value required to bind to. + * Spring defaults to a command name of "command" but this can be overridden + * by user config. + *# +#macro( springBind $path ) + #if("$!springHtmlEscape" != "") + #set( $status = $springMacroRequestContext.getBindStatus($path, $springHtmlEscape) ) + #else + #set( $status = $springMacroRequestContext.getBindStatus($path) ) + #end +#end + +#** + * springBindEscaped + * + * Similar to springBind, but takes an explicit HTML escape flag rather + * than relying on the default HTML escape setting. + *# +#macro( springBindEscaped $path $htmlEscape ) + #set( $status = $springMacroRequestContext.getBindStatus($path, $htmlEscape) ) +#end + +#** + * springFormInput + * + * Display a form input field of type 'text' and bind it to an attribute + * of a command or bean. + * + * @param path the name of the field to bind to + * @param attributes any additional attributes for the element (such as class + * or CSS styles or size + * + *# +#macro( springFormInput $path $attributes ) + #springBind($path) + <input type="text" name="${status.expression}" value="$!status.value" ${attributes}#springCloseTag() +#end + +#** + * springFormPasswordInput + * + * Display a form input field of type 'password' and bind it to an attribute + * of a command or bean. No value will ever be specified for this field regardless + * of whether one exists or not. For hopefully obvious reasons! + * + * @param path the name of the field to bind to + * @param attributes any additional attributes for the element (such as class + * or CSS styles or size + * + *# +#macro( springFormPasswordInput $path $attributes ) + #springBind($path) + <input type="password" name="${status.expression}" value="" ${attributes}#springCloseTag() +#end + +#** + * springFormHiddenInput + * + * Generate a form input field of type 'hidden' and bind it to an attribute + * of a command or bean. + * + * @param path the name of the field to bind to + * @param attributes any additional attributes for the element (such as class + * or CSS styles or size + * + *# +#macro( springFormHiddenInput $path $attributes ) + #springBind($path) + <input type="hidden" name="${status.expression}" value="$!status.value" ${attributes}#springCloseTag() +#end + +#** + * formTextArea + * + * display a text area and bind it to an attribute + * of a command or bean + * + * @param path the name of the field to bind to + * @param attributes any additional attributes for the element (such as class + * or CSS styles or size + * + *# +#macro( springFormTextarea $path $attributes ) + #springBind($path) + <textarea name="${status.expression}" ${attributes}>$!status.value</textarea> +#end + +#** + * springFormSingleSelect + * + * Show a selectbox (dropdown) input element allowing a single value to be chosen + * from a list of options. + * + * The null check for $status.value leverages Velocity's 'quiet' notation rather + * than the more common #if($status.value) since this method evaluates to the + * boolean 'false' if the content of $status.value is the String "false" - not + * what we want. + * + * @param path the name of the field to bind to + * @param options a map (value=label) of all the available options + * @param attributes any additional attributes for the element (such as class + * or CSS styles or size +*# +#macro( springFormSingleSelect $path $options $attributes ) + #springBind($path) + <select name="${status.expression}" ${attributes}> + #foreach($option in $options.keySet()) + <option value="${option}" + #if("$!status.value" == "$option") + selected="selected" + #end> + ${options.get($option)}</option> + #end + </select> +#end + +#** + * springFormMultiSelect + * + * Show a listbox of options allowing the user to make 0 or more choices from + * the list of options. + * + * @param path the name of the field to bind to + * @param options a map (value=label) of all the available options + * @param attributes any additional attributes for the element (such as class + * or CSS styles or size +*# +#macro( springFormMultiSelect $path $options $attributes ) + #springBind($path) + <select multiple="multiple" name="${status.expression}" ${attributes}> + #foreach($option in $options.keySet()) + <option value="${option}" + #foreach($item in $status.value) + #if($item == $option) + selected="selected" + #end + #end + >${options.get($option)}</option> + #end + </select> +#end + +#** + * springFormRadioButtons + * + * Show radio buttons. + * + * @param path the name of the field to bind to + * @param options a map (value=label) of all the available options + * @param separator the html tag or other character list that should be used to + * separate each option. Typically ' ' or '<br>' + * @param attributes any additional attributes for the element (such as class + * or CSS styles or size +*# +#macro( springFormRadioButtons $path $options $separator $attributes ) + #springBind($path) + #foreach($option in $options.keySet()) + <input type="radio" name="${status.expression}" value="${option}" + #if("$!status.value" == "$option") + checked="checked" + #end + ${attributes} + #springCloseTag() + ${options.get($option)} ${separator} + #end +#end + +#** + * springFormCheckboxes + * + * Show checkboxes. + * + * @param path the name of the field to bind to + * @param options a map (value=label) of all the available options + * @param separator the html tag or other character list that should be used to + * separate each option. Typically ' ' or '<br>' + * @param attributes any additional attributes for the element (such as class + * or CSS styles or size +*# +#macro( springFormCheckboxes $path $options $separator $attributes ) + #springBind($path) + #foreach($option in $options.keySet()) + <input type="checkbox" name="${status.expression}" value="${option}" + #foreach($item in $status.value) + #if($item == $option) + checked="checked" + #end + #end + ${attributes} #springCloseTag() + ${options.get($option)} ${separator} + #end +#end + +#** + * springShowErrors + * + * Show validation errors for the currently bound field, with + * optional style attributes. + * + * @param separator the html tag or other character list that should be used to + * separate each option. Typically '<br>'. + * @param classOrStyle either the name of a CSS class element (which is defined in + * the template or an external CSS file) or an inline style. If the value passed in here + * contains a colon (:) then a 'style=' attribute will be used, else a 'class=' attribute + * will be used. +*# +#macro( springShowErrors $separator $classOrStyle ) + #foreach($error in $status.errorMessages) + #if($classOrStyle == "") + <b>${error}</b> + #else + #if($classOrStyle.indexOf(":") == -1) + #set($attr="class") + #else + #set($attr="style") + #end + <span ${attr}="${classOrStyle}">${error}</span> + #end + ${separator} + #end +#end + +#** + * springCloseTag + * + * Simple macro to close an HTML tag that has no body with '>' or '/>', + * depending on the value of a 'springXhtmlCompliant' variable in the + * template context. + *# +#macro( springCloseTag )#if($springXhtmlCompliant)/>#else>#end #end diff --git a/java/management/core/lib/xmlbeans/jsr173_api.jar b/java/management/core/lib/xmlbeans/jsr173_api.jar Binary files differnew file mode 100644 index 0000000000..d6fdfad49b --- /dev/null +++ b/java/management/core/lib/xmlbeans/jsr173_api.jar diff --git a/java/management/core/lib/xmlbeans/resolver.jar b/java/management/core/lib/xmlbeans/resolver.jar Binary files differnew file mode 100644 index 0000000000..073d789675 --- /dev/null +++ b/java/management/core/lib/xmlbeans/resolver.jar diff --git a/java/management/core/lib/xmlbeans/saxon8.jar b/java/management/core/lib/xmlbeans/saxon8.jar Binary files differnew file mode 100644 index 0000000000..f3a2484882 --- /dev/null +++ b/java/management/core/lib/xmlbeans/saxon8.jar diff --git a/java/management/core/lib/xmlbeans/xbean.jar b/java/management/core/lib/xmlbeans/xbean.jar Binary files differnew file mode 100644 index 0000000000..08c72cd5b7 --- /dev/null +++ b/java/management/core/lib/xmlbeans/xbean.jar diff --git a/java/management/core/lib/xmlbeans/xbean_xpath.jar b/java/management/core/lib/xmlbeans/xbean_xpath.jar Binary files differnew file mode 100644 index 0000000000..c3366ebc8b --- /dev/null +++ b/java/management/core/lib/xmlbeans/xbean_xpath.jar diff --git a/java/management/core/lib/xmlbeans/xmlpublic.jar b/java/management/core/lib/xmlbeans/xmlpublic.jar Binary files differnew file mode 100644 index 0000000000..8c79b44c47 --- /dev/null +++ b/java/management/core/lib/xmlbeans/xmlpublic.jar diff --git a/java/management/core/src/log4j.properties b/java/management/core/src/log4j.properties new file mode 100644 index 0000000000..367153b2d9 --- /dev/null +++ b/java/management/core/src/log4j.properties @@ -0,0 +1,6 @@ +log4j.rootCategory=${amqj.logging.level}, console + +log4j.appender.console=org.apache.log4j.ConsoleAppender +log4j.appender.console.Threshold=DEBUG +log4j.appender.console.layout=org.apache.log4j.PatternLayout +log4j.appender.console.layout.ConversionPattern=%t %d %p [%c{4}] %m%n diff --git a/java/management/core/src/org/apache/qpid/management/ManagementConnection.java b/java/management/core/src/org/apache/qpid/management/ManagementConnection.java new file mode 100644 index 0000000000..1dbfe6826c --- /dev/null +++ b/java/management/core/src/org/apache/qpid/management/ManagementConnection.java @@ -0,0 +1,120 @@ +/* + * + * Copyright (c) 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.qpid.management; + +import org.apache.qpid.AMQException; +import org.apache.qpid.url.URLSyntaxException; +import org.apache.qpid.management.messaging.ManagementDestination; +import org.apache.qpid.jms.Session; +import org.apache.qpid.jms.MessageProducer; +import org.apache.qpid.client.AMQConnection; +import org.apache.qpid.client.AMQQueue; +import org.apache.log4j.Logger; + +import javax.jms.*; + +public class ManagementConnection +{ + private static final Logger _log = Logger.getLogger(ManagementConnection.class); + + private String _brokerHost; + + private int _brokerPort; + + private String _username; + + private String _password; + + private String _virtualPath; + + private AMQConnection _connection; + + private Session _session; + + private MessageConsumer _consumer; + + private MessageProducer _producer; + + private AMQQueue _replyQueue; + + public ManagementConnection(String brokerHost, int brokerPort, String username, + String password, String virtualPath) + { + _brokerHost = brokerHost; + _brokerPort = brokerPort; + _username = username; + _password = password; + _virtualPath = virtualPath; + } + + public void connect() throws AMQException, JMSException, URLSyntaxException + { + _connection = new AMQConnection(_brokerHost, _brokerPort, _username, _password, + "clientName" + System.currentTimeMillis(), _virtualPath); + _connection.setExceptionListener(new ExceptionListener() + { + public void onException(JMSException jmsException) + { + _log.error("Error occurred: " + jmsException, jmsException); + try + { + _connection.close(); + } + catch (JMSException e) + { + _log.error("Error closing connection: " + e, e); + } + } + }); + _session = (Session)_connection.createSession(false, Session.CLIENT_ACKNOWLEDGE); + _replyQueue = new AMQQueue("response", true) + { + public String getEncodedName() + { + return getQueueName(); + } + }; + _consumer = _session.createConsumer(_replyQueue, 100, true, true, null); + + _producer = (MessageProducer) _session.createProducer(new ManagementDestination()); + _connection.start(); + } + + /** + * Send a request and wait for a response. + * @param xmlRequest the request to send + * @return the response received from the broker + * @throws AMQException when an AMQ error occurs + * @throws JMSException when a JMS error occurs + */ + public TextMessage sendRequest(String xmlRequest) throws AMQException, JMSException + { + TextMessage requestMsg = _session.createTextMessage(xmlRequest); + requestMsg.setJMSReplyTo(_replyQueue); + _producer.send(requestMsg); + return (TextMessage) _consumer.receive(); + } + + public void close() throws AMQException, JMSException + { + if (_connection != null) + { + _connection.close(); + } + } +} diff --git a/java/management/core/src/org/apache/qpid/management/jmx/AMQConsole.java b/java/management/core/src/org/apache/qpid/management/jmx/AMQConsole.java new file mode 100644 index 0000000000..c312ef63bf --- /dev/null +++ b/java/management/core/src/org/apache/qpid/management/jmx/AMQConsole.java @@ -0,0 +1,95 @@ +/* + * + * Copyright (c) 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.qpid.management.jmx; + +import org.apache.log4j.Logger; +import org.apache.xmlbeans.XmlException; +import org.apache.qpid.AMQException; +import org.apache.qpid.url.URLSyntaxException; +import org.apache.qpid.management.ManagementConnection; +import org.apache.qpid.management.messaging.CMLMessageFactory; +import org.apache.qpid.schema.cml.CmlDocument; + +import javax.jms.JMSException; +import javax.jms.TextMessage; +import javax.management.MBeanServer; +import java.lang.management.ManagementFactory; + +/** + * Main entry point for AMQ console implementation. + * + */ +public class AMQConsole +{ + private static final Logger _log = Logger.getLogger(AMQConsole.class); + + private ManagementConnection _connection; + + private MBeanInfoRegistry _mbeanInfoRegistry; + + private MBeanRegistrar _mbeanRegistrar; + + private MBeanServer _mbeanServer; + + public AMQConsole(String host, int port, String username, String password, + String context) + { + _connection = new ManagementConnection(host, port, username, password, context); + } + + public void initialise() throws AMQException, JMSException, XmlException, URLSyntaxException + { + _connection.connect(); + createMBeanInfo(); + _mbeanServer = ManagementFactory.getPlatformMBeanServer(); + _mbeanRegistrar = new MBeanRegistrar(_mbeanServer, _connection, _mbeanInfoRegistry); + } + + public void registerAllMBeans() throws JMSException, AMQException + { + _mbeanRegistrar.registerAllMBeans(); + } + + private void createMBeanInfo() throws JMSException, AMQException, XmlException + { + TextMessage tm = _connection.sendRequest(CMLMessageFactory.createSchemaRequest()); + if (_log.isDebugEnabled()) + { + _log.debug("Response document: \n" + tm.getText()); + } + CmlDocument cmlDoc = CmlDocument.Factory.parse(tm.getText()); + _mbeanInfoRegistry = new MBeanInfoRegistry(cmlDoc); + } + + public static void main(String[] args) + { + AMQConsole console = new AMQConsole(args[0], Integer.parseInt(args[1]), args[2], args[3], + args[4]); + try + { + console.initialise(); + _log.info("Registering all MBeans..."); + console.registerAllMBeans(); + _log.info("MBean registration completed successfully"); + } + catch (Exception e) + { + _log.error("Console initialisation error: " + e, e); + } + } +} diff --git a/java/management/core/src/org/apache/qpid/management/jmx/AMQMBeanInfo.java b/java/management/core/src/org/apache/qpid/management/jmx/AMQMBeanInfo.java new file mode 100644 index 0000000000..9663a7f783 --- /dev/null +++ b/java/management/core/src/org/apache/qpid/management/jmx/AMQMBeanInfo.java @@ -0,0 +1,40 @@ +/* + * + * Copyright (c) 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.qpid.management.jmx; + +import javax.management.openmbean.OpenMBeanAttributeInfo; +import java.util.Map; +import java.util.HashMap; + +public class AMQMBeanInfo +{ + private Map<String, OpenMBeanAttributeInfo> _name2AttributeInfoMap = new HashMap<String, OpenMBeanAttributeInfo>(); + + public AMQMBeanInfo(OpenMBeanAttributeInfo[] attributeInfos) + { + for (OpenMBeanAttributeInfo attributeInfo: attributeInfos) + { + _name2AttributeInfoMap.put(attributeInfo.getName(), attributeInfo); + } + } + + public OpenMBeanAttributeInfo getAttributeInfo(String name) + { + return _name2AttributeInfoMap.get(name); + } +} diff --git a/java/management/core/src/org/apache/qpid/management/jmx/CMLMBean.java b/java/management/core/src/org/apache/qpid/management/jmx/CMLMBean.java new file mode 100644 index 0000000000..2d1dafb9f0 --- /dev/null +++ b/java/management/core/src/org/apache/qpid/management/jmx/CMLMBean.java @@ -0,0 +1,298 @@ +/* + * + * Copyright (c) 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.qpid.management.jmx; + +import org.apache.log4j.Logger; +import org.apache.qpid.AMQException; +import org.apache.qpid.management.ManagementConnection; +import org.apache.qpid.management.messaging.CMLMessageFactory; +import org.apache.qpid.schema.cml.CmlDocument; +import org.apache.qpid.schema.cml.FieldType; +import org.apache.qpid.schema.cml.InspectReplyType; +import org.apache.qpid.schema.cml.MethodReplyType; + +import javax.jms.JMSException; +import javax.jms.TextMessage; +import javax.management.*; +import javax.management.openmbean.OpenMBeanAttributeInfo; +import javax.management.openmbean.OpenMBeanInfoSupport; +import javax.management.openmbean.OpenType; +import javax.management.openmbean.SimpleType; +import java.util.Hashtable; + +public class CMLMBean implements DynamicMBean +{ + private static final Logger _log = Logger.getLogger(CMLMBean.class); + + /** + * The number of milliseconds after which data values are considered "stale" and will be + * refreshed by querying the broker. This is a way of ensure that reading attributes + * repeatedly does not hit the broker heavily. + */ + private static final long REFRESH_IN_MILLIS = 2000; + + /** + * Name of the attribute for the parent MBean + */ + public static final String PARENT_ATTRIBUTE = "__parent"; + + private OpenMBeanInfoSupport _mbeanInfo; + + private AMQMBeanInfo _extraMbeanInfo; + + /** + * The cached inspect reply. This is used to read attribute values and is refreshed automatically + * if a request for an attribute is made after the time interval specified in REFRESH_IN_MILLIS + */ + private InspectReplyType _inspectReply; + + private CMLMBean _parent; + + private ObjectName _objectName; + + private ManagementConnection _connection; + + private int _objectId; + + private long _lastRefreshTime = System.currentTimeMillis(); + + public CMLMBean(CMLMBean parent, OpenMBeanInfoSupport mbeanInfo, AMQMBeanInfo extraMbeanInfo, + InspectReplyType inspectReply, ManagementConnection connection, int objectId) + { + _mbeanInfo = mbeanInfo; + _extraMbeanInfo = extraMbeanInfo; + _inspectReply = inspectReply; + _parent = parent; + _connection = connection; + _objectId = objectId; + } + + /** + * Utility method that populates all the type infos up to the root. Used when + * constructing the ObjectName. + * We end up with properties of the form "className", "objectId" in the map. + * @param leaf the child node. Must not be null. Note that the child types are not populated since the + * convention is different for the child where instead of "className" the word "type" is + * used. See the JMX Best Practices document on the Sun JMX website for details. + * @param properties + */ + public static void populateAllTypeInfo(Hashtable<String, String> properties, CMLMBean leaf) + { + CMLMBean current = leaf.getParent(); + while (current != null) + { + properties.put(current.getType(), Integer.toString(current.getObjectId())); + current = current.getParent(); + } + } + + public String getType() + { + return _inspectReply.getClass1(); + } + + public int getObjectId() + { + return _inspectReply.getObject2(); + } + + public InspectReplyType getInspectReply() + { + return _inspectReply; + } + + public CMLMBean getParent() + { + return _parent; + } + + public ObjectName getObjectName() + { + return _objectName; + } + + public void setObjectName(ObjectName objectName) + { + _objectName = objectName; + } + + public Object getAttribute(String attribute) + throws AttributeNotFoundException, MBeanException, ReflectionException + { + if (PARENT_ATTRIBUTE.equals(attribute)) + { + if (_parent == null) + { + return null; + } + else + { + return _parent.getObjectName(); + } + } + if (needRefresh()) + { + refreshValues(); + } + String nsDecl = "declare namespace cml='http://www.amqp.org/schema/cml';"; + FieldType[] fields = (FieldType[]) _inspectReply.selectPath(nsDecl + "$this/cml:field[@name='" + + attribute + "']"); + if (fields == null || fields.length == 0) + { + throw new AttributeNotFoundException("Attribute " + attribute + " not found"); + } + else + { + OpenMBeanAttributeInfo attrInfo = _extraMbeanInfo.getAttributeInfo(attribute); + OpenType openType = attrInfo.getOpenType(); + String value = fields[0].getStringValue(); + try + { + return createAttributeValue(openType, value, attrInfo.getName()); + } + catch (MalformedObjectNameException e) + { + throw new MBeanException(e); + } + } + } + + private boolean needRefresh() + { + return ((System.currentTimeMillis() - _lastRefreshTime) > REFRESH_IN_MILLIS); + } + + private void refreshValues() throws MBeanException + { + _log.debug("Refreshing values..."); + try + { + TextMessage response = _connection.sendRequest(CMLMessageFactory.createInspectRequest(_objectId)); + + CmlDocument cmlDoc = CmlDocument.Factory.parse(response.getText()); + _inspectReply = cmlDoc.getCml().getInspectReply(); + _lastRefreshTime = System.currentTimeMillis(); + } + catch (Exception e) + { + throw new MBeanException(e); + } + } + + private Object createAttributeValue(OpenType openType, String value, String mbeanType) + throws MalformedObjectNameException + { + if (openType.equals(SimpleType.STRING)) + { + return value; + } + else if (openType.equals(SimpleType.BOOLEAN)) + { + return Boolean.valueOf(value); + } + else if (openType.equals(SimpleType.INTEGER)) + { + return Integer.valueOf(value); + } + else if (openType.equals(SimpleType.DOUBLE)) + { + return Double.valueOf(value); + } + else if (openType.equals(SimpleType.OBJECTNAME)) + { + Hashtable<String, String> props = new Hashtable<String, String>(); + props.put("objectid", value); + props.put("type", mbeanType); + // this populates all type info for parents + populateAllTypeInfo(props, this); + // add in type info for this level. This information is available from the inspect reply xml fragment + props.put(_inspectReply.getClass1(), Integer.toString(_inspectReply.getObject2())); + return new ObjectName(JmxConstants.JMX_DOMAIN, props); + } + else + { + _log.warn("Unsupported open type: " + openType + " - returning string value"); + return value; + } + } + + public void setAttribute(Attribute attribute) throws AttributeNotFoundException, InvalidAttributeValueException, + MBeanException, ReflectionException + { + + } + + public AttributeList getAttributes(String[] attributes) + { + AttributeList al = new AttributeList(attributes.length); + for (String name : attributes) + { + try + { + Object value = getAttribute(name); + final Attribute attr = new Attribute(name, value); + al.add(attr); + } + catch (Exception e) + { + _log.error("Unable to get value for attribute: " + name, e); + } + } + return al; + } + + public AttributeList setAttributes(AttributeList attributes) + { + return null; + } + + public Object invoke(String actionName, Object params[], String signature[]) throws MBeanException, + ReflectionException + { + _log.debug("Invoke called on action " + actionName); + try + { + TextMessage response = _connection.sendRequest(CMLMessageFactory.createMethodRequest(_objectId, actionName)); + CmlDocument cmlDoc = CmlDocument.Factory.parse(response.getText()); + CmlDocument.Cml cml = cmlDoc.getCml(); + MethodReplyType methodReply = cml.getMethodReply(); + if (methodReply.getStatus() != MethodReplyType.Status.OK) + { + throw new MBeanException(new Exception("Response code from method: " + methodReply.getStatus())); + } + return null; + } + catch (AMQException e) + { + throw new MBeanException(e); + } + catch (JMSException e) + { + throw new MBeanException(e); + } + catch (org.apache.xmlbeans.XmlException e) + { + throw new MBeanException(e); + } + } + + public MBeanInfo getMBeanInfo() + { + return _mbeanInfo; + } +} diff --git a/java/management/core/src/org/apache/qpid/management/jmx/JmxConstants.java b/java/management/core/src/org/apache/qpid/management/jmx/JmxConstants.java new file mode 100644 index 0000000000..a1944bfeb1 --- /dev/null +++ b/java/management/core/src/org/apache/qpid/management/jmx/JmxConstants.java @@ -0,0 +1,23 @@ +/* + * + * Copyright (c) 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.qpid.management.jmx; + +public interface JmxConstants +{ + String JMX_DOMAIN = "org.apache.qpid"; +} diff --git a/java/management/core/src/org/apache/qpid/management/jmx/MBeanInfoRegistry.java b/java/management/core/src/org/apache/qpid/management/jmx/MBeanInfoRegistry.java new file mode 100644 index 0000000000..f6abb5028b --- /dev/null +++ b/java/management/core/src/org/apache/qpid/management/jmx/MBeanInfoRegistry.java @@ -0,0 +1,201 @@ +/* + * + * Copyright (c) 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.qpid.management.jmx; + +import org.apache.qpid.AMQException; +import org.apache.qpid.schema.cml.CmlDocument; +import org.apache.qpid.schema.cml.FieldType; +import org.apache.qpid.schema.cml.MethodType; +import org.apache.qpid.schema.cml.SchemaReplyType; + +import javax.management.modelmbean.DescriptorSupport; +import javax.management.openmbean.*; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Stores all OpenMBeanInfo instances. + * <p/> + * Builds MBeanInfo instances from the CML schema (which is parsed by XMLBeans) and + * stores these indexed by CML class name. + * <p/> + * When constructing a DynamicMBean this registry is consulted for the MBeanInfo. + * + */ +public class MBeanInfoRegistry +{ + private Map<String, OpenMBeanInfoSupport> _cmlClass2OpenMBeanInfoMap = new HashMap<String, OpenMBeanInfoSupport>(); + + private Map<String, AMQMBeanInfo> _cmlClass2AMQMBeanInfoMap = new HashMap<String, AMQMBeanInfo>(); + + public MBeanInfoRegistry(CmlDocument cmlDocument) throws AMQException + { + initialise(cmlDocument); + } + + private void initialise(CmlDocument cmlDocument) throws AMQException + { + CmlDocument.Cml cml = cmlDocument.getCml(); + SchemaReplyType schema = cml.getSchemaReply(); + for (org.apache.qpid.schema.cml.ClassType c : schema.getClass1List()) + { + OpenMBeanAttributeInfo[] attributes = createAttributeInfos(c.getFieldList()); + OpenMBeanOperationInfo[] operations = createOperationInfos(c.getMethodList()); + String className = c.getName(); + OpenMBeanInfoSupport support = new OpenMBeanInfoSupport(className, null, attributes, + null, operations, null); + // we need to store the extra information separately since we cannot subclass + // OpenMBeanInfoSupport. Doing so means we need to have an AMQMBeanInfo class on each client + // which defeats the point of OpenMBeans. The extra info is only used by the CMLBean implementation + // to assist with runtime value lookups. + AMQMBeanInfo extra = new AMQMBeanInfo(attributes); + _cmlClass2OpenMBeanInfoMap.put(className, support); + _cmlClass2AMQMBeanInfoMap.put(className, extra); + } + } + + public OpenMBeanInfoSupport getOpenMBeanInfo(String cmlType) + { + return _cmlClass2OpenMBeanInfoMap.get(cmlType); + } + + public AMQMBeanInfo getAMQMBeanInfo(String cmlType) + { + return _cmlClass2AMQMBeanInfoMap.get(cmlType); + } + + private OpenMBeanAttributeInfo[] createAttributeInfos(List<FieldType> fields) + throws AMQException + { + OpenMBeanAttributeInfo[] attributes = new OpenMBeanAttributeInfo[fields.size() + 1]; + + // we up the parent attribute which is always present + try + { + DescriptorSupport descriptor = new DescriptorSupport(new String[]{"hidden=true"}); + attributes[attributes.length - 1] = new OpenMBeanAttributeInfoSupport(CMLMBean.PARENT_ATTRIBUTE, + "Parent", SimpleType.OBJECTNAME, + true, false, false); + //descriptor); JDK 1.6 only + } + catch (Exception e) + { + // should never happen + throw new AMQException("Unable to create Parent attribute", e); + } + // add all the type-specific attributes + for (int i = 0; i < attributes.length - 1; i++) + { + FieldType field = fields.get(i); + OpenType openType = getOpenType(field.getType(), field.getModify()); + String description = field.getLabel(); + attributes[i] = new OpenMBeanAttributeInfoSupport(field.getName(), + description != null ? description:"No description", + openType, + true, + field.getModify(), + openType == SimpleType.BOOLEAN); + } + + return attributes; + } + + private static OpenType getOpenType(FieldType.Type.Enum type, boolean isArray) + throws UnsupportedCMLTypeException, AMQException + { + SimpleType simpleType; + boolean primitive; + switch (type.intValue()) + { + // the constants are not public (bug in xmlbeans) so we cannot use + // the constants that are defined + // TODO: raise defect with xmlbeans projects + case 1: + simpleType = SimpleType.BOOLEAN; + primitive = true; + break; + case 2: + simpleType = SimpleType.STRING; + primitive = false; + break; + case 3: + simpleType = SimpleType.INTEGER; + primitive = true; + break; + case 4: + simpleType = SimpleType.OBJECTNAME; + primitive = false; + break; + case 5: + simpleType = SimpleType.DATE; + primitive = false; + break; + default: + throw new UnsupportedCMLTypeException(type.toString()); + } + if (isArray) + { + try + { + //return new ArrayType(simpleType, primitive); + return new ArrayType(1, simpleType); + } + catch (OpenDataException e) + { + throw new AMQException("Error constructing array type: " + e, e); + } + } + else + { + return simpleType; + } + } + + private OpenMBeanOperationInfo[] createOperationInfos(List<MethodType> methods) + throws AMQException + { + OpenMBeanOperationInfo[] methodInfos = new OpenMBeanOperationInfo[methods.size()]; + for (int i = 0; i < methodInfos.length; i++) + { + MethodType methodType = methods.get(i); + OpenMBeanParameterInfo[] parameters = createParameterInfos(methodType.getFieldList()); + methodInfos[i] = new OpenMBeanOperationInfoSupport(methodType.getName(), "No description", + parameters, SimpleType.VOID, + OpenMBeanOperationInfoSupport.ACTION); + } + return methodInfos; + } + + private OpenMBeanParameterInfo[] createParameterInfos(List<FieldType> parameters) + throws AMQException + { + OpenMBeanParameterInfo[] paramInfos = new OpenMBeanParameterInfo[parameters.size()]; + for (int i = 0; i < paramInfos.length; i++) + { + FieldType field = parameters.get(i); + String description = field.getLabel(); + OpenType openType = getOpenType(field.getType(), field.getModify()); + paramInfos[i] = new OpenMBeanParameterInfoSupport(field.getName(), + description==null?"No description":description, + openType); + } + return paramInfos; + } +} + diff --git a/java/management/core/src/org/apache/qpid/management/jmx/MBeanRegistrar.java b/java/management/core/src/org/apache/qpid/management/jmx/MBeanRegistrar.java new file mode 100644 index 0000000000..bdc3772553 --- /dev/null +++ b/java/management/core/src/org/apache/qpid/management/jmx/MBeanRegistrar.java @@ -0,0 +1,141 @@ +/* + * + * Copyright (c) 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.qpid.management.jmx; + +import org.apache.log4j.Logger; +import org.apache.xmlbeans.XmlException; +import org.apache.qpid.AMQException; +import org.apache.qpid.management.ManagementConnection; +import org.apache.qpid.management.messaging.CMLMessageFactory; +import org.apache.qpid.schema.cml.CmlDocument; +import org.apache.qpid.schema.cml.FieldType; +import org.apache.qpid.schema.cml.InspectReplyType; + +import javax.jms.JMSException; +import javax.jms.TextMessage; +import javax.management.MBeanAttributeInfo; +import javax.management.MBeanServer; +import javax.management.ObjectName; +import javax.management.openmbean.OpenMBeanAttributeInfo; +import javax.management.openmbean.SimpleType; +import javax.management.openmbean.OpenMBeanInfoSupport; +import java.util.Hashtable; + +/** + * Responsible for registering MBeans. This class will navigate through + * our hierarchy of MBeans, registering them with the appropriate ObjectNames. + * + */ +public class MBeanRegistrar +{ + private static final Logger _log = Logger.getLogger(MBeanRegistrar.class); + + /** The MBean server with which all MBeans will be registered. */ + private MBeanServer _targetMBeanServer; + + /** The connection used to communicate with the broker */ + private ManagementConnection _connection; + + private MBeanInfoRegistry _mbeanInfoRegistry; + + /** + * Create a registrar for the specified MBean server + * @param targetMBeanServer the MBean server with which all MBeans will be registered + */ + public MBeanRegistrar(MBeanServer targetMBeanServer, ManagementConnection connection, + MBeanInfoRegistry mbeanInfoRegistry) + { + _targetMBeanServer = targetMBeanServer; + _connection = connection; + _mbeanInfoRegistry = mbeanInfoRegistry; + } + + public void registerAllMBeans() throws AMQException, JMSException + { + registerMBean(null, 0); + } + + /** + * Asks the broker for details of a particular object id then creates and registers an + * MBean with the MBeanServer. + * @param objectId id of the object we want to inspect + * @return the registered bean, from which the underlying inspect response can be retrieved if required + * @throws AMQException + * @throws JMSException + */ + private CMLMBean registerMBean(CMLMBean parent, int objectId) throws AMQException, JMSException + { + TextMessage response = _connection.sendRequest(CMLMessageFactory.createInspectRequest(objectId)); + try + { + CmlDocument cmlDoc = CmlDocument.Factory.parse(response.getText()); + CmlDocument.Cml cml = cmlDoc.getCml(); + InspectReplyType inspect = cml.getInspectReply(); + if (_log.isDebugEnabled()) + { + _log.debug("Inspect reply: " + inspect); + } + OpenMBeanInfoSupport mbeanInfo = _mbeanInfoRegistry.getOpenMBeanInfo(inspect.getClass1()); + AMQMBeanInfo extraMbeanInfo = _mbeanInfoRegistry.getAMQMBeanInfo(inspect.getClass1()); + CMLMBean mbean = new CMLMBean(parent, mbeanInfo, extraMbeanInfo, inspect, _connection, objectId); + Hashtable<String, String> props = new Hashtable<String, String>(); + props.put("objectid", Integer.toString(objectId)); + props.put("type", mbean.getType()); + CMLMBean.populateAllTypeInfo(props, mbean); + ObjectName mbeanObjectName = new ObjectName("org.apache.qpid", props); + mbean.setObjectName(mbeanObjectName); + _targetMBeanServer.registerMBean(mbean, mbeanObjectName); + + // recursively register all beans + String nsDecl = "declare namespace cml='http://www.amqp.org/schema/cml';"; + for (MBeanAttributeInfo attributeInfo: mbeanInfo.getAttributes()) + { + OpenMBeanAttributeInfo openAttributeInfo = (OpenMBeanAttributeInfo) attributeInfo; + if (openAttributeInfo.getOpenType().equals(SimpleType.OBJECTNAME) && + !"__parent".equals(openAttributeInfo.getName())) + { + if (_log.isDebugEnabled()) + { + _log.debug("Searching for fields with name: " + openAttributeInfo.getName()); + } + FieldType[] fields = (FieldType[]) inspect.selectPath(nsDecl + "$this/cml:field[@name='" + + openAttributeInfo.getName() + "']"); + if (fields == null || fields.length == 0) + { + throw new AMQException("inspect xml did not contain field value for field " + + attributeInfo.getName()); + } + for (FieldType field : fields) + { + registerMBean(mbean, Integer.parseInt(field.getStringValue())); + } + } + } + return mbean; + } + catch (XmlException e) + { + throw new AMQException(_log, "Error parsing broker response: " + e, e); + } + catch (Exception e) + { + e.printStackTrace(); + throw new AMQException(_log, "Error registering MBean: " + e, e); + } + } +} diff --git a/java/management/core/src/org/apache/qpid/management/jmx/UnsupportedCMLTypeException.java b/java/management/core/src/org/apache/qpid/management/jmx/UnsupportedCMLTypeException.java new file mode 100644 index 0000000000..bb866f8d17 --- /dev/null +++ b/java/management/core/src/org/apache/qpid/management/jmx/UnsupportedCMLTypeException.java @@ -0,0 +1,36 @@ +/* + * + * Copyright (c) 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.qpid.management.jmx; + +import org.apache.qpid.AMQException; + +public class UnsupportedCMLTypeException extends AMQException +{ + private String _type; + + public UnsupportedCMLTypeException(String type) + { + super("CML type " + type + " is unsupported by the JMX layer"); + _type = type; + } + + public String getType() + { + return _type; + } +} diff --git a/java/management/core/src/org/apache/qpid/management/messaging/CMLMessageFactory.java b/java/management/core/src/org/apache/qpid/management/messaging/CMLMessageFactory.java new file mode 100644 index 0000000000..e47eb66c65 --- /dev/null +++ b/java/management/core/src/org/apache/qpid/management/messaging/CMLMessageFactory.java @@ -0,0 +1,59 @@ +/* + * + * Copyright (c) 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.qpid.management.messaging; + +import org.apache.qpid.schema.cml.CmlDocument; +import org.apache.qpid.schema.cml.InspectRequestType; +import org.apache.qpid.schema.cml.MethodRequestType; + +public class CMLMessageFactory +{ + public static String createSchemaRequest() + { + CmlDocument cmlDoc = CmlDocument.Factory.newInstance(); + CmlDocument.Cml cml = createStandardCml(cmlDoc); + cml.addNewSchemaRequest(); + return cmlDoc.toString(); + } + + public static String createInspectRequest(int objectId) + { + CmlDocument cmlDoc = CmlDocument.Factory.newInstance(); + CmlDocument.Cml cml = createStandardCml(cmlDoc); + InspectRequestType inspect = cml.addNewInspectRequest(); + inspect.setObject(objectId); + return cmlDoc.toString(); + } + + public static String createMethodRequest(int objectId, String methodName) + { + CmlDocument cmlDoc = CmlDocument.Factory.newInstance(); + CmlDocument.Cml cml = createStandardCml(cmlDoc); + MethodRequestType methodReq = cml.addNewMethodRequest(); + methodReq.setObject(objectId); + methodReq.setName(methodName); + return cmlDoc.toString(); + } + + private static CmlDocument.Cml createStandardCml(CmlDocument cmlDoc) + { + CmlDocument.Cml cml = cmlDoc.addNewCml(); + cml.setVersion("1.0"); + return cml; + } +} diff --git a/java/management/core/src/org/apache/qpid/management/messaging/ManagementDestination.java b/java/management/core/src/org/apache/qpid/management/messaging/ManagementDestination.java new file mode 100644 index 0000000000..f6edb9394a --- /dev/null +++ b/java/management/core/src/org/apache/qpid/management/messaging/ManagementDestination.java @@ -0,0 +1,43 @@ +/* + * + * Copyright (c) 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.qpid.management.messaging; + +import org.apache.qpid.client.AMQDestination; + +public class ManagementDestination extends AMQDestination +{ + public ManagementDestination() + { + super("amq.system", "system", "amq.console"); + } + + public boolean isNameRequired() + { + return false; + } + + public String getEncodedName() + { + return null; + } + + public String getRoutingKey() + { + return getDestinationName(); + } +} diff --git a/java/management/core/test/org/apache/qpid/management/harness/SimpleJMXClient.java b/java/management/core/test/org/apache/qpid/management/harness/SimpleJMXClient.java new file mode 100644 index 0000000000..68e1325b1d --- /dev/null +++ b/java/management/core/test/org/apache/qpid/management/harness/SimpleJMXClient.java @@ -0,0 +1,25 @@ +/* + * + * Copyright (c) 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.qpid.management.harness; + +public class SimpleJMXClient +{ + + + +} diff --git a/java/management/core/test/org/apache/qpid/management/schema/TestParseSchema.java b/java/management/core/test/org/apache/qpid/management/schema/TestParseSchema.java new file mode 100644 index 0000000000..8672207e59 --- /dev/null +++ b/java/management/core/test/org/apache/qpid/management/schema/TestParseSchema.java @@ -0,0 +1,87 @@ +/* + * + * Copyright (c) 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.qpid.management.schema; + +import org.apache.log4j.Logger; +import org.apache.qpid.management.ManagementConnection; +import org.apache.qpid.management.messaging.CMLMessageFactory; +import org.apache.qpid.schema.cml.CmlDocument; + +import javax.jms.TextMessage; + +public class TestParseSchema +{ + private static final Logger _logger = Logger.getLogger(TestParseSchema.class); + + private static ManagementConnection _con; + + private static void parseCMLSchema(String xml) throws Exception + { + CmlDocument cmlDoc = CmlDocument.Factory.parse(xml); + CmlDocument.Cml cml = cmlDoc.getCml(); + /*SchemaReplyDocument.SchemaReply schema = cml.getSchemaReply(); + for (ClassDocument.Class classDefn: schema.getClass1List()) + { + System.out.println("Class: " + classDefn.getName()); + } */ + } + + public static void main(String[] args) + { + _logger.info("Starting..."); + + if (args.length != 5) + { + System.out.println("Usage: host port username password vhost"); + System.exit(1); + } + try + { + _con = new ManagementConnection(args[0], Integer.parseInt(args[1]), args[2], args[3], + args[4]); + + _con.connect(); + TextMessage tm = _con.sendRequest(CMLMessageFactory.createSchemaRequest()); + parseCMLSchema(tm.getText()); + _logger.info("Closing management connection"); + _con.close(); + + //_logger.info("Waiting..."); + } + catch (Throwable t) + { + _logger.error("Fatal error: " + t, t); + } + finally + { + if (_con != null) + { + _logger.info("Closing connection"); + try + { + _con.close(); + } + catch (Exception e) + { + _logger.error("Error closing connection: " + e); + } + } + } + + } +} diff --git a/java/management/mc4j/qpid/BlazeConnections.xml b/java/management/mc4j/qpid/BlazeConnections.xml new file mode 100644 index 0000000000..b75f49d95b --- /dev/null +++ b/java/management/mc4j/qpid/BlazeConnections.xml @@ -0,0 +1,84 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + - + - Copyright (c) 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. + - + --> +<!DOCTYPE Dashboard PUBLIC "-//MC4J//DTD Dashboard 1.0//EN" "http://mc4j.sourceforge.net/Dashboard_1_0.dtd"> + +<Dashboard version="1.0" name="Qpid AMQ Connections Statistics"> + + <Description>This dashboard shows the statistics of all Qpid Client Connections.</Description> + + <DashboardMatch type="Global" location="/Qpid/Connections"> + <BeanMatch id="ConnectionBeanList" type="Multiple"> + <Condition type="BeanObjectNameCondition" filter="type=Connection"/> + </BeanMatch> + </DashboardMatch> + + <LayoutManager type="java.awt.BorderLayout"/> + <Content> + + <!-- *** The header section displays title and a refresh control *** --> + <Component type="javax.swing.JPanel"> + <Constraint type="BorderConstraints" direction="NORTH"/> + <LayoutManager type="java.awt.BorderLayout"/> + <Border type="javax.swing.border.EmptyBorder" top="(Literal)2" left="(Literal)5" bottom="(Literal)2" right="(Literal)5"/> + <Content> + <Component type="javax.swing.JPanel"> + <Constraint type="BorderConstraints" direction="CENTER"/> + <LayoutManager type="java.awt.BorderLayout"/> + <Content> + <Component type="javax.swing.JLabel" id="titleLable"> + <Constraint type="BorderConstraints" direction="CENTER"/> + <Attribute name="text" value="DashboardName"/> + <Attribute name="font" value="(Literal)SansSerif bold 20"/> + <Attribute name="foreground" value="(Literal)0x666666"/> + </Component> + <Component type="javax.swing.JTextArea"> + <Constraint type="BorderConstraints" direction="SOUTH"/> + <Attribute name="text" value="DashboardDescription"/> + <Attribute name="font" value="(Literal)DialogInput bold 14"/> + <Attribute name="opaque" value="(Literal)false"/> + <Attribute name="editable" value="(Literal)false"/> + </Component> + </Content> + </Component> + <Component type="org.mc4j.console.dashboard.components.RefreshControlComponent"> + <Constraint type="BorderConstraints" direction="EAST"/> + <Attribute name="refreshDelay" value="(Literal)1000"/> + </Component> + </Content> + </Component> + + + <Component type="org.mc4j.console.dashboard.components.AttributeTableComponent"> + <Attribute name="beanList" value="ConnectionBeanList"/> + <Constraint type="BorderConstraints" direction="CENTER"/> + + <Attribute name="background" value="(Literal)0xFFFFFF"/> + <Attribute name="preferredSize" value="100,100"/> + + + + <Attribute name="AttributeName" value="(Literal)RemoteAddress"/> + <Attribute name="AttributeName" value="(Literal)ReadBytes"/> + <Attribute name="AttributeName" value="(Literal)WrittenBytes"/> + <Attribute name="AttributeName" value="(Literal)LastIoTime"/> + </Component> + + + </Content> +</Dashboard> diff --git a/java/management/mc4j/qpid/BlazeExchanges.xml b/java/management/mc4j/qpid/BlazeExchanges.xml new file mode 100644 index 0000000000..6612c711c3 --- /dev/null +++ b/java/management/mc4j/qpid/BlazeExchanges.xml @@ -0,0 +1,81 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + - + - Copyright (c) 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. + - + --> +<!DOCTYPE Dashboard PUBLIC "-//MC4J//DTD Dashboard 1.0//EN" "http://mc4j.sourceforge.net/Dashboard_1_0.dtd"> + +<Dashboard version="1.0" name="Qpid AMQ Exchanges"> + + <Description>This dashboard shows the statistics of all Qpid Exchanges.</Description> + + <DashboardMatch type="Global" location="/Qpid/Exchanges"> + <BeanMatch id="ConnectionBeanList" type="Multiple"> + <Condition type="BeanObjectNameCondition" filter="type=Exchange"/> + </BeanMatch> + </DashboardMatch> + + <LayoutManager type="java.awt.BorderLayout"/> + <Content> + + <!-- *** The header section displays title and a refresh control *** --> + <Component type="javax.swing.JPanel"> + <Constraint type="BorderConstraints" direction="NORTH"/> + <LayoutManager type="java.awt.BorderLayout"/> + <Border type="javax.swing.border.EmptyBorder" top="(Literal)2" left="(Literal)5" bottom="(Literal)2" right="(Literal)5"/> + <Content> + <Component type="javax.swing.JPanel"> + <Constraint type="BorderConstraints" direction="CENTER"/> + <LayoutManager type="java.awt.BorderLayout"/> + <Content> + <Component type="javax.swing.JLabel" id="titleLable"> + <Constraint type="BorderConstraints" direction="CENTER"/> + <Attribute name="text" value="DashboardName"/> + <Attribute name="font" value="(Literal)SansSerif bold 20"/> + <Attribute name="foreground" value="(Literal)0x666666"/> + </Component> + <Component type="javax.swing.JTextArea"> + <Constraint type="BorderConstraints" direction="SOUTH"/> + <Attribute name="text" value="DashboardDescription"/> + <Attribute name="font" value="(Literal)DialogInput bold 14"/> + <Attribute name="opaque" value="(Literal)false"/> + <Attribute name="editable" value="(Literal)false"/> + </Component> + </Content> + </Component> + <Component type="org.mc4j.console.dashboard.components.RefreshControlComponent"> + <Constraint type="BorderConstraints" direction="EAST"/> + <Attribute name="refreshDelay" value="(Literal)1000"/> + </Component> + </Content> + </Component> + + + <Component type="org.mc4j.console.dashboard.components.AttributeTableComponent"> + <Attribute name="beanList" value="ConnectionBeanList"/> + <Constraint type="BorderConstraints" direction="CENTER"/> + + <Attribute name="background" value="(Literal)0xFFFFFF"/> + <Attribute name="preferredSize" value="100,100"/> + + <Attribute name="AttributeName" value="(Literal)Name"/> + <Attribute name="AttributeName" value="(Literal)Durable"/> + <Attribute name="AttributeName" value="(Literal)Bindings"/> + </Component> + + + </Content> +</Dashboard> diff --git a/java/management/mc4j/qpid/BlazeQueues.xml b/java/management/mc4j/qpid/BlazeQueues.xml new file mode 100644 index 0000000000..4a6e55cdb7 --- /dev/null +++ b/java/management/mc4j/qpid/BlazeQueues.xml @@ -0,0 +1,83 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + - + - Copyright (c) 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. + - + --> +<!DOCTYPE Dashboard PUBLIC "-//MC4J//DTD Dashboard 1.0//EN" "http://mc4j.sourceforge.net/Dashboard_1_0.dtd"> + +<Dashboard version="1.0" name="Qpid AMQ Queues"> + + <Description>This dashboard shows the statistics of all Qpid Queues.</Description> + + <DashboardMatch type="Global" location="/Qpid/Queues"> + <BeanMatch id="ConnectionBeanList" type="Multiple"> + <Condition type="BeanObjectNameCondition" filter="type=Queue"/> + </BeanMatch> + </DashboardMatch> + + <LayoutManager type="java.awt.BorderLayout"/> + <Content> + + <!-- *** The header section displays title and a refresh control *** --> + <Component type="javax.swing.JPanel"> + <Constraint type="BorderConstraints" direction="NORTH"/> + <LayoutManager type="java.awt.BorderLayout"/> + <Border type="javax.swing.border.EmptyBorder" top="(Literal)2" left="(Literal)5" bottom="(Literal)2" right="(Literal)5"/> + <Content> + <Component type="javax.swing.JPanel"> + <Constraint type="BorderConstraints" direction="CENTER"/> + <LayoutManager type="java.awt.BorderLayout"/> + <Content> + <Component type="javax.swing.JLabel" id="titleLable"> + <Constraint type="BorderConstraints" direction="CENTER"/> + <Attribute name="text" value="DashboardName"/> + <Attribute name="font" value="(Literal)SansSerif bold 20"/> + <Attribute name="foreground" value="(Literal)0x666666"/> + </Component> + <Component type="javax.swing.JTextArea"> + <Constraint type="BorderConstraints" direction="SOUTH"/> + <Attribute name="text" value="DashboardDescription"/> + <Attribute name="font" value="(Literal)DialogInput bold 14"/> + <Attribute name="opaque" value="(Literal)false"/> + <Attribute name="editable" value="(Literal)false"/> + </Component> + </Content> + </Component> + <Component type="org.mc4j.console.dashboard.components.RefreshControlComponent"> + <Constraint type="BorderConstraints" direction="EAST"/> + <Attribute name="refreshDelay" value="(Literal)1000"/> + </Component> + </Content> + </Component> + + + <Component type="org.mc4j.console.dashboard.components.AttributeTableComponent"> + <Attribute name="beanList" value="ConnectionBeanList"/> + <Constraint type="BorderConstraints" direction="CENTER"/> + + <Attribute name="background" value="(Literal)0xFFFFFF"/> + <Attribute name="preferredSize" value="100,100"/> + + <Attribute name="AttributeName" value="(Literal)Name"/> + <Attribute name="AttributeName" value="(Literal)AutoDelete"/> + <Attribute name="AttributeName" value="(Literal)Durable"/> + <Attribute name="AttributeName" value="(Literal)Owner"/> + <Attribute name="AttributeName" value="(Literal)MessageCount"/> + </Component> + + + </Content> +</Dashboard> diff --git a/java/management/mc4j/qpid/BlazeSingleQueue.xml b/java/management/mc4j/qpid/BlazeSingleQueue.xml new file mode 100644 index 0000000000..0879801746 --- /dev/null +++ b/java/management/mc4j/qpid/BlazeSingleQueue.xml @@ -0,0 +1,99 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + - + - Copyright (c) 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. + - + --> +<!DOCTYPE Dashboard PUBLIC "-//MC4J//DTD Dashboard 1.0//EN" "http://mc4j.sourceforge.net/Dashboard_1_0.dtd"> + +<Dashboard version="1.0" name="Qpid Queue Statistics Graph"> + + <Description>This dashboard shows the statistics of a Qpid Queue</Description> + + <DashboardMatch type="Bean"> + <BeanMatch id="QueueNode" type="Single"> + <Condition type="BeanObjectNameCondition" filter="type=Queue"/> + </BeanMatch> + </DashboardMatch> + + <LayoutManager type="java.awt.BorderLayout"/> + <Content> + + <!-- *** The header section displays title and a refresh control *** --> + <Component type="javax.swing.JPanel"> + <Constraint type="BorderConstraints" direction="NORTH"/> + <LayoutManager type="java.awt.BorderLayout"/> + <Border type="javax.swing.border.EmptyBorder" top="(Literal)2" left="(Literal)5" bottom="(Literal)2" right="(Literal)5"/> + <Content> + <Component type="javax.swing.JPanel"> + <Constraint type="BorderConstraints" direction="CENTER"/> + <LayoutManager type="java.awt.BorderLayout"/> + <Content> + <Component type="javax.swing.JLabel" id="titleLable"> + <Constraint type="BorderConstraints" direction="CENTER"/> + <Attribute name="text" value="DashboardName"/> + <Attribute name="font" value="(Literal)SansSerif bold 20"/> + <Attribute name="foreground" value="(Literal)0x666666"/> + </Component> + <Component type="javax.swing.JTextArea"> + <Constraint type="BorderConstraints" direction="SOUTH"/> + <Attribute name="text" value="DashboardDescription"/> + <Attribute name="font" value="(Literal)DialogInput bold 14"/> + <Attribute name="opaque" value="(Literal)false"/> + <Attribute name="editable" value="(Literal)false"/> + </Component> + </Content> + </Component> + </Content> + </Component> + + + <!-- *** Scroll pane of info *** --> + <Component type="javax.swing.JScrollPane"> + <Attribute name="background" value="(Literal)0xFFFFFF"/> + <Content> + <Component type="javax.swing.JPanel"> + <Attribute name="background" value="(Literal)0xFFFFFF"/> + <Constraint type="BorderConstraints" direction="CENTER"/> + <Attribute name="preferredSize" value="100,100"/> + <LayoutManager type="java.awt.BoxLayout" axis="Y_AXIS"/> + <Content> + + <Component type="org.mc4j.console.swing.SectionHolder"> + <Attribute name="title" value="(Literal)Queue Depth"/> + <Attribute name="background" value="(Literal)0xFFFFFF"/> + <LayoutManager type="java.awt.GridLayout" rows="1" cols="1"/> + <Content> + <Component type="org.mc4j.console.dashboard.components.NumericAttributeGraph"> + <Attribute name="beanNode" value="QueueNode"/> + + <Attribute name="preferredSize" value="(Literal)400,150"/> + <Attribute name="attributeName" value="(Literal)MessageCount"/> + </Component> + </Content> + </Component> + + <Component type="org.mc4j.console.dashboard.components.FillerComponent"> + <Attribute name="type" value="(Literal)VERTICAL_GLUE_SHAPE"/> + </Component> + </Content> + + </Component> + </Content> + </Component> + + + </Content> +</Dashboard> diff --git a/java/management/webapp/META-INF/context.xml b/java/management/webapp/META-INF/context.xml new file mode 100644 index 0000000000..1d3d5683b9 --- /dev/null +++ b/java/management/webapp/META-INF/context.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + - + - Copyright (c) 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. + - + --> +<Context path="/"> +</Context> diff --git a/java/management/webapp/WEB-INF/web.xml b/java/management/webapp/WEB-INF/web.xml new file mode 100644 index 0000000000..db467779bf --- /dev/null +++ b/java/management/webapp/WEB-INF/web.xml @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + - + - Copyright (c) 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. + - + --> + +<web-app version="2.4" + 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" > +</web-app> |
