diff options
author | Rajith Muditha Attapattu <rajith@apache.org> | 2011-05-27 15:44:23 +0000 |
---|---|---|
committer | Rajith Muditha Attapattu <rajith@apache.org> | 2011-05-27 15:44:23 +0000 |
commit | 66765100f4257159622cefe57bed50125a5ad017 (patch) | |
tree | a88ee23bb194eb91f0ebb2d9b23ff423e3ea8e37 /qpid/java/broker-plugins/experimental | |
parent | 1aeaa7b16e5ce54f10c901d75c4d40f9f88b9db6 (diff) | |
parent | 88b98b2f4152ef59a671fad55a0d08338b6b78ca (diff) | |
download | qpid-python-66765100f4257159622cefe57bed50125a5ad017.tar.gz |
Creating a branch for experimenting with some ideas for JMS client.rajith_jms_client
git-svn-id: https://svn.apache.org/repos/asf/qpid/branches/rajith_jms_client@1128369 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'qpid/java/broker-plugins/experimental')
28 files changed, 2726 insertions, 0 deletions
diff --git a/qpid/java/broker-plugins/experimental/info/MANIFEST.MF b/qpid/java/broker-plugins/experimental/info/MANIFEST.MF new file mode 100644 index 0000000000..f213104d8d --- /dev/null +++ b/qpid/java/broker-plugins/experimental/info/MANIFEST.MF @@ -0,0 +1,16 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: QpidPlugin +Bundle-SymbolicName: qpid_info_plugin;singleton:=true +Bundle-License: http://www.apache.org/licenses/LICENSE-2.0.txt +Bundle-Version: 1.0.0 +Bundle-Activator: org.apache.qpid.info.Activator +Import-Package: org.apache.qpid.server.configuration, + org.osgi.framework, + org.apache.qpid.common, + org.apache.qpid.server.registry +Bundle-RequiredExecutionEnvironment: JavaSE-1.6 +Bundle-ClassPath: . +Bundle-ActivationPolicy: lazy +Export-Package: org.apache.qpid.info;uses:="org.osgi.framework" + diff --git a/qpid/java/broker-plugins/experimental/info/build.properties b/qpid/java/broker-plugins/experimental/info/build.properties new file mode 100644 index 0000000000..bdbbe1c2af --- /dev/null +++ b/qpid/java/broker-plugins/experimental/info/build.properties @@ -0,0 +1,31 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# +source.. = src/ +output.. = bin/ +bin.includes = META-INF/,\ + .,\ + plugin.xml,\ + lib/eventTrackerClient-2.7.0.jar,\ + lib/commons-logging-1.0.4.jar +src.includes = src/,\ + plugin.xml,\ + lib/,\ + build.properties,\ + bin/,\ + META-INF/ diff --git a/qpid/java/broker-plugins/experimental/info/build.xml b/qpid/java/broker-plugins/experimental/info/build.xml new file mode 100644 index 0000000000..c5881aa839 --- /dev/null +++ b/qpid/java/broker-plugins/experimental/info/build.xml @@ -0,0 +1,32 @@ +<!-- + - + - Licensed to the Apache Software Foundation (ASF) under one +nn - or more contributor license agreements. See the NOTICE file + -n distributed with this work for additional information + - regarding copyright ownership. The ASF licenses this file + - to you under the Apache License, Version 2.0 (the + - "License"); you may not use this file except in compliance + - with the License. You may obtain a copy of the License at + - + - http://www.apache.org/licenses/LICENSE-2.0 + - + - Unless required by applicable law or agreed to in writing, + - software distributed under the License is distributed on an + - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + - KIND, either express or implied. See the License for the + - specific language governing permissions and limitations + - under the License. + - + --> +<project name="AMQ Broker Info Plugin" default="build"> + + <property name="module.depends" value="common broker broker-plugins"/> + <property name="module.test.depends" value="test broker/test management/common client systests common/test"/> + <property name="module.manifest" value="MANIFEST.MF"/> + <property name="module.plugin" value="true"/> + + <import file="../../../module.xml"/> + + <target name="bundle" depends="bundle-tasks"/> + +</project> diff --git a/qpid/java/broker-plugins/experimental/info/src/main/java/org/apache/qpid/info/Activator.java b/qpid/java/broker-plugins/experimental/info/src/main/java/org/apache/qpid/info/Activator.java new file mode 100644 index 0000000000..c7d3fd38ff --- /dev/null +++ b/qpid/java/broker-plugins/experimental/info/src/main/java/org/apache/qpid/info/Activator.java @@ -0,0 +1,204 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +package org.apache.qpid.info; + +import org.apache.qpid.info.util.HttpPoster; +import org.apache.qpid.info.util.IniFileReader; +import org.apache.qpid.info.util.SoapClient; +import org.osgi.framework.BundleActivator; +import org.osgi.framework.BundleContext; + +import java.io.File; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.Properties; + +/** The Activator class for the OSGI info service */ +public class Activator implements BundleActivator +{ + + private final List<String> _soapPropList = Arrays.asList("soap.hostname", + "soap.port", "soap.path", "soap.action", "soap.envelope"); + + private final List<String> _httpPropList = Arrays.asList("http.url", + "http.envelope"); + + InfoServiceImpl _service = null; + + BundleContext _ctx = null; + + /** + * Start bundle method + * + * @param ctx the bundle context + */ + public void start(BundleContext ctx) throws Exception + { + if (null != ctx) + { + _ctx = ctx; + _service = new InfoServiceImpl(); + ctx.registerService(InfoService.class.getName(), _service, null); + sendInfo("STARTUP"); + } + } + + /** + * Stop the bundle method + * + * @param ctx the bundle context + */ + public void stop(BundleContext ctx) throws Exception + { + sendInfo("SHUTDOWN"); + } + + /** + * Sends the information message + * + * @param action label that identifies if we are starting up or shutting down + */ + private void sendInfo(String action) + { + if ((null == _ctx) && (null == _service)) + { + // invalid state + return; + } + + IniFileReader ifr = new IniFileReader(); + try + { + String QPID_HOME = System.getProperty("QPID_HOME"); + String cfgFilePath = QPID_HOME + File.separator + "etc" + + File.separator + "qpidinfo.ini"; + ifr.load(cfgFilePath); + } + catch (Throwable ex) + { + // drop everything to be silent + return; + } + + // Only send Messages if we have some sections. + if (ifr.getSections().size() != 0) + { + Info<? extends Map<String, ?>> info = _service.invoke(action); + String protocol = ifr.getSections().get("").getProperty("protocol"); + sendMessages(protocol, ifr, info); + } + } + + /** + * Sends all the messages configured in the properties file + * + * @param protocol indicates what protocol to be used: http and soap implemented + * for now + * @param ifr an instance of IniFileReader class + * @param info an instance of an Info object, encapsulating the information + * we want to send + */ + private void sendMessages(String protocol, IniFileReader ifr, + Info<? extends Map<String, ?>> info) + { + if (null != protocol) + { + // Set the global properties first (as they are the defaults) + Properties defaultProps = ifr.getSections().get(""); + if (protocol.toLowerCase().startsWith("http")) + { + for (String section : ifr.getSections().keySet()) + { + // Skip the defaults + if (section.equals("")) + { + continue; + } + Properties props = new Properties(); + props.putAll(defaultProps); + props.putAll(ifr.getSections().get(section)); + if (isValid(protocol, props)) + { + new HttpPoster(props, info.toXML()).run(); + } + } + + } + else if (protocol.toLowerCase().startsWith("soap")) + { + for (String section : ifr.getSections().keySet()) + { + Properties props = new Properties(); + props.putAll(defaultProps); + props.putAll(ifr.getSections().get(section)); + if (isValid(protocol, props)) + { + new SoapClient(info.toMap(), props).sendSOAPMessage(); + } + } + } + } + } + + /** + * Checks if the properties for a specified protocol are valid + * + * @param protocol String representing the protocol + * @param props The properties associate with the specified protocol + * @return boolean + */ + private boolean isValid(String protocol, Properties props) + { + if (null == protocol) + { + return false; + } + String value = ""; + if (protocol.toLowerCase().startsWith("http")) + { + for (String prop : _httpPropList) + { + if (null == props.get(prop)) + { + return false; + } + } + return true; + } + + if (protocol.toLowerCase().startsWith("soap")) + { + for (String prop : _soapPropList) + { + value = props.getProperty(prop); + if (null == value) + { + return false; + } + } + return true; + } + return false; + } +} // end class + diff --git a/qpid/java/broker-plugins/experimental/info/src/main/java/org/apache/qpid/info/AppInfo.java b/qpid/java/broker-plugins/experimental/info/src/main/java/org/apache/qpid/info/AppInfo.java new file mode 100644 index 0000000000..a5d267282b --- /dev/null +++ b/qpid/java/broker-plugins/experimental/info/src/main/java/org/apache/qpid/info/AppInfo.java @@ -0,0 +1,94 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +package org.apache.qpid.info; + +import org.apache.qpid.common.QpidProperties; +import org.apache.qpid.server.configuration.ServerConfiguration; +import org.apache.qpid.server.registry.ApplicationRegistry; + +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Properties; +import java.util.TreeMap; + +/** AppInfo class is gathering application specific information */ +public class AppInfo +{ + + private static final List<String> appProps = Arrays.asList("QPID_HOME", + "QPID_WORK"); + + private static Map<String, String> appInfoMap = new TreeMap<String, String>(); + + /** + * getInfo method retrieves a key-value map for specific application properties + * + * @return Map<String,String> + */ + public static Map<String, String> getInfo() + { + + // Gather the selected app props + Properties sysprops = System.getProperties(); + String propName; + for (Iterator<Entry<Object, Object>> it = sysprops.entrySet() + .iterator(); it.hasNext();) + { + Entry<Object, Object> en = it.next(); + propName = en.getKey().toString(); + if (appProps.indexOf(propName) >= 0) + { + appInfoMap.put(propName, en.getValue().toString()); + } + } + + ServerConfiguration sc; + try + { + sc = ApplicationRegistry.getInstance().getConfiguration(); + if (null != sc) + { + appInfoMap.put("jmxport", sc.getJMXManagementPort() + ""); + appInfoMap.put("port", sc.getPorts().toString()); + appInfoMap.put("version", QpidProperties.getReleaseVersion()); + appInfoMap.put("vhosts", "standalone"); + appInfoMap.put("JMXPrincipalDatabase", sc + .getJMXPrincipalDatabase()); + appInfoMap.put("KeystorePath", sc.getKeystorePath()); + appInfoMap.put("PluginDirectory", sc.getPluginDirectory()); + appInfoMap.put("CertType", sc.getCertType()); + appInfoMap.put("QpidWork", sc.getQpidWork()); + appInfoMap.put("Bind", sc.getBind()); + } + } + catch (Exception e) + { + // drop everything to be silent + } + return appInfoMap; + + } + +} diff --git a/qpid/java/broker-plugins/experimental/info/src/main/java/org/apache/qpid/info/Info.java b/qpid/java/broker-plugins/experimental/info/src/main/java/org/apache/qpid/info/Info.java new file mode 100644 index 0000000000..2fb9382526 --- /dev/null +++ b/qpid/java/broker-plugins/experimental/info/src/main/java/org/apache/qpid/info/Info.java @@ -0,0 +1,143 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +/** + * + * @author sorin + * + * Info object + */ + +package org.apache.qpid.info; + +import org.apache.qpid.info.util.XMLWriter; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.Properties; + +/** + * The Info class encapsulates all the information we are collecting + * and it is able to render it in different data representations + */ +public class Info<T extends Map<String, ?>> +{ + private T _info; + + /** + * Constructor. + * + * @param info instantiates the object with a Map<String,?> + */ + public Info(T info) + { + _info = info; + } + + @Override + public String toString() + { + String result = ""; + for (Iterator<String> it = _info.keySet().iterator(); it.hasNext();) + { + String str = it.next(); + result += str + "=" + _info.get(str).toString() + "\n"; + } + return result; + } + + /** + * Renders Info map to a property object + * + * @return A Properties object representing the Info map + */ + public Properties toProps() + { + Properties props = new Properties(); + if (null == _info) + { + return null; + } + for (Iterator<String> it = _info.keySet().iterator(); it.hasNext();) + { + String key = it.next(); + props.put(key, _info.get(key)); + } + return props; + } + + /** + * Renders Info map to a StringBuffer + * + * @return A StringBuffer object representing the Info map + */ + public StringBuffer toStringBuffer() + { + StringBuffer sb = new StringBuffer(); + for (Iterator<String> it = _info.keySet().iterator(); it.hasNext();) + { + String str = it.next(); + sb.append(str + "=" + _info.get(str).toString() + "\n"); + } + return sb; + } + + /** + * Renders Info map to a StringBuffer containing an XML string + * + * @return A StringBuffer object containing an XML representation of the Info map + */ + public StringBuffer toXML() + { + XMLWriter xw = new XMLWriter(new StringBuffer()); + xw.writeXMLHeader(); + Map<String, String> attr = new HashMap<String, String>(); + xw.writeOpenTag("qpidinfo", attr); + String key; + for (Iterator<String> it = _info.keySet().iterator(); it.hasNext();) + { + attr.clear(); + key = it.next(); + xw.writeTag(key, attr, _info.get(key).toString()); + } + xw.writeCloseTag("qpidinfo"); + return xw.getXML(); + } + + /** + * Renders Info map to a HashMap + * + * @return A HashMap object representing the Info map + */ + public HashMap<String, String> toMap() + { + String key; + HashMap<String, String> infoMap = new HashMap<String, String>(); + for (Iterator<String> it = _info.keySet().iterator(); it.hasNext();) + { + key = it.next(); + infoMap.put(key, _info.get(key).toString()); + } + return infoMap; + } + +} diff --git a/qpid/java/broker-plugins/experimental/info/src/main/java/org/apache/qpid/info/InfoService.java b/qpid/java/broker-plugins/experimental/info/src/main/java/org/apache/qpid/info/InfoService.java new file mode 100644 index 0000000000..2804dfb1b4 --- /dev/null +++ b/qpid/java/broker-plugins/experimental/info/src/main/java/org/apache/qpid/info/InfoService.java @@ -0,0 +1,30 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + + /** + * Interface exposing the service methods + */ + package org.apache.qpid.info; + + public interface InfoService + { + public Info<?> invoke(String action); + } diff --git a/qpid/java/broker-plugins/experimental/info/src/main/java/org/apache/qpid/info/InfoServiceImpl.java b/qpid/java/broker-plugins/experimental/info/src/main/java/org/apache/qpid/info/InfoServiceImpl.java new file mode 100644 index 0000000000..5522f2701e --- /dev/null +++ b/qpid/java/broker-plugins/experimental/info/src/main/java/org/apache/qpid/info/InfoServiceImpl.java @@ -0,0 +1,66 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +/** + * + * @author sorin + * + * Implementation for Info service + */ + +package org.apache.qpid.info; + +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Map; +import java.util.SortedMap; +import java.util.TreeMap; + + +public class InfoServiceImpl implements InfoService +{ + + SortedMap<String, String> infoMap = new TreeMap<String, String>(); + + /** + * invoke method collects all the information from System and Application + * and encapsulates them in an Info object + * @return An instance of an Info object + */ + public Info<? extends Map<String,?>> invoke(String action) + { + // Record the action (STARTUP/SHUTDOWN) + infoMap.put("action",action); + + // Record the current time stamp + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSSZ"); + infoMap.put("time", sdf.format(Calendar.getInstance().getTime())); + + // Add the system specific properties + infoMap.putAll(SystemInfo.getInfo()); + + // Add the application specific properties + infoMap.putAll(AppInfo.getInfo()); + + return new Info<SortedMap<String, String>>(infoMap); + } + +} diff --git a/qpid/java/broker-plugins/experimental/info/src/main/java/org/apache/qpid/info/SystemInfo.java b/qpid/java/broker-plugins/experimental/info/src/main/java/org/apache/qpid/info/SystemInfo.java new file mode 100644 index 0000000000..8bd94fe14d --- /dev/null +++ b/qpid/java/broker-plugins/experimental/info/src/main/java/org/apache/qpid/info/SystemInfo.java @@ -0,0 +1,91 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +package org.apache.qpid.info; + +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.TreeMap; +import java.util.Map.Entry; + +/** + * Collector for system specific information + */ +public class SystemInfo +{ + + private static Map<String, String> sysInfoMap = new TreeMap<String, String>(); + + private static final List<String> sysProps = Arrays.asList( + "java.class.path", "java.home", "java.vm.name", "java.vm.vendor", + "java.vm.version", "java.class.version", "java.runtime.version", + "os.arch", "os.name", "os.version", "sun.arch.data.model", + "user.home", "user.dir", "user.name", "user.timezone"); + + /** + * getInfo collects all the properties specified in sysprops list + * @return A Map<String,String> + */ + public static Map<String, String> getInfo() + { + + // Get the hostname + try + { + InetAddress addr = InetAddress.getLocalHost(); + String hostname = addr.getHostName(); + sysInfoMap.put("hostname", hostname); + sysInfoMap.put("ip", addr.getHostAddress()); + } + catch (UnknownHostException e) + { + // drop everything to be silent + } + // Get the runtime info + sysInfoMap.put("CPUCores", Runtime.getRuntime().availableProcessors() + + ""); + sysInfoMap.put("Maximum_Memory", Runtime.getRuntime().maxMemory() + ""); + sysInfoMap.put("Free_Memory", Runtime.getRuntime().freeMemory() + ""); + + // Gather the selected system props + Properties sysprops = System.getProperties(); + String propName; + for (Iterator<Entry<Object, Object>> it = sysprops.entrySet() + .iterator(); it.hasNext();) + { + Entry<Object, Object> en = it.next(); + propName = en.getKey().toString(); + if (sysProps.indexOf(propName) >= 0) + { + sysInfoMap.put(propName, en.getValue().toString()); + } + } + + return sysInfoMap; + + } + +} diff --git a/qpid/java/broker-plugins/experimental/info/src/main/java/org/apache/qpid/info/util/HttpPoster.java b/qpid/java/broker-plugins/experimental/info/src/main/java/org/apache/qpid/info/util/HttpPoster.java new file mode 100644 index 0000000000..d27980be05 --- /dev/null +++ b/qpid/java/broker-plugins/experimental/info/src/main/java/org/apache/qpid/info/util/HttpPoster.java @@ -0,0 +1,130 @@ +/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+package org.apache.qpid.info.util;
+
+import java.util.ArrayList;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Properties;
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
+import java.net.InetAddress;
+import java.net.URL;
+import java.net.URLConnection;
+import java.net.UnknownHostException;
+
+/**
+ *
+ * An simple Http post class for qpid info service
+ */
+public class HttpPoster implements Runnable
+{
+ private final String _url;
+
+ private final Hashtable<String, String> _header;
+
+ private final List<String> _response = new ArrayList<String>();
+
+ private final StringBuffer _buf;
+
+ /**
+ * Constructor
+ *
+ * @param props Properties containing the URL
+ * @param buf Buffer containing the message to be posted
+ */
+ public HttpPoster(Properties props, StringBuffer buf)
+ {
+ _buf = buf;
+ if (null != props)
+ {
+ _url = props.getProperty("http.url");
+ _header = new Hashtable<String, String>();
+ try
+ {
+ String hostname = InetAddress.getLocalHost().getHostName();
+ _header.put("hostname", hostname);
+ }
+ catch (UnknownHostException e)
+ {
+ // Silently ignoring the error ;)
+ }
+ }
+ else
+ {
+ _url = null;
+ _header = null;
+ }
+ }
+
+ /** Posts the message from the _buf StringBuffer to the http server */
+ public void run()
+ {
+ if (null == _url)
+ {
+ return;
+ }
+ String line;
+ URL urlDest;
+ URLConnection urlConn;
+ try
+ {
+ urlDest = new URL(_url);
+ urlConn = urlDest.openConnection();
+ urlConn.setDoOutput(true);
+ urlConn.setUseCaches(false);
+ for (Iterator<String> it = _header.keySet().iterator(); it.hasNext();)
+ {
+ String prop = it.next();
+ urlConn.setRequestProperty(prop, _header.get(prop));
+ }
+ OutputStreamWriter wr =
+ new OutputStreamWriter(urlConn.getOutputStream());
+ wr.write(_buf.toString());
+ wr.flush();
+ // Get the response
+ BufferedReader rd = new BufferedReader(new InputStreamReader(
+ urlConn.getInputStream()));
+ while ((line = rd.readLine()) != null)
+ {
+ _response.add(line);
+ }
+ }
+ catch (Exception ex)
+ {
+ // Silently ignoring the error ;)
+ }
+ }
+
+ /**
+ * Retrieves the response from the http server
+ *
+ * @return List<String> response received from the http server
+ */
+ public List<String> get_response()
+ {
+ return _response;
+ }
+
+}
diff --git a/qpid/java/broker-plugins/experimental/info/src/main/java/org/apache/qpid/info/util/IniFileReader.java b/qpid/java/broker-plugins/experimental/info/src/main/java/org/apache/qpid/info/util/IniFileReader.java new file mode 100644 index 0000000000..60a025d322 --- /dev/null +++ b/qpid/java/broker-plugins/experimental/info/src/main/java/org/apache/qpid/info/util/IniFileReader.java @@ -0,0 +1,193 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +package org.apache.qpid.info.util; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; + +/** + * This class is simple implementation of an ini file reader. It expects a + * file with the following structure: + * + * ; global values, can be overwritten in sections + * key1=value1 + * key2=value2 + * + * [Section1] + * key1=value1_new ; overwriting the global key1 + * key3=value3 + * key4=value4 + * + * [Section2] + * key5=value5 + * key6=value6 + * key7=value7 + * + * Note: Commentaries are preceded by ; or # and are supported throughout + * A commentary line at the end of section is interpreted as + * a section end marker + * + * A structure <String,Properties> (section name, associated properties) + * is generated as a result of processing the ini file. + */ +public class IniFileReader +{ + private final Map<String, Properties> _sections; + + private final String COMMENT_SEMICOLON = ";"; + + private final String COMMENT_HASH = "#"; + + enum State + { + IN_SECTION, OFF_SECTION, GLOBAL + } + + /* + * IniFileReader constructor + */ + + public IniFileReader() + { + _sections = new HashMap<String, Properties>(); + } + + /** + * Cleans up the after comments or the empty spaces/tabs surrounding the given string + * + * @param str The String to be cleaned + * + * @return String Cleanup Version + */ + private String cleanUp(String str) + { + if (str.contains(COMMENT_SEMICOLON)) + { + str = str.substring(0, str.indexOf(COMMENT_SEMICOLON)); + } + if (str.contains(COMMENT_HASH)) + { + str = str.substring(0, str.indexOf(COMMENT_HASH)); + } + return str.trim(); + } + + /** + * Loads and parses the ini file with the full path specified in the argument + * + * @param fileName Full path to the ini file + * + * @throws IllegalArgumentException If the file cannot be processed + */ + public void load(String fileName) throws IllegalArgumentException + { + if (!new File(fileName).isFile()) + { + throw new IllegalArgumentException("File: " + fileName + " does not exist or cannot be read."); + } + State state = State.GLOBAL; + String line; + Properties sectionProps = new Properties(); + String sectionName = ""; + try + { + BufferedReader in = new BufferedReader(new FileReader(fileName)); + while ((line = in.readLine()) != null) + { + String str = cleanUp(line); + + // Did we get a section header? + if (str.startsWith("[")) + { + if (!str.endsWith("]")) + { + // Index of 1 to skip '[' + throw new IllegalArgumentException(str.substring(1) + + " is not closed"); + } + + // We encountered a new section header + if (state != State.IN_SECTION) + { + _sections.put(sectionName, sectionProps); + sectionProps = new Properties(); + sectionName = str.replace("[", "").replace("]", "") + .trim(); + state = State.IN_SECTION; + } + } + + // Any other line tested separately, ignore if out of a section + // and add if in section + if (str.length() == 0) + { + // We encountered a commented or an empty line, both cases + // mean we are off the section + if (state == State.IN_SECTION) + { + _sections.put(sectionName, sectionProps); + state = State.OFF_SECTION; + } + } + else + { + // proper line, add it to the props + if (state != State.OFF_SECTION) + { + if (str.contains("=")) + { + int ix = str.indexOf("="); + sectionProps.put(str.substring(0, ix).trim(), str + .substring(ix + 1).trim()); + } + } + } + } + in.close(); + } + catch (IOException e) + { + _sections.clear(); + return; + } + if (state != State.OFF_SECTION) + { + _sections.put(sectionName, sectionProps); + } + } + + /** + * Getter for the Sections Map + * + * @return Map<String,Properties> The parsed content of the ini file in this structure + */ + public Map<String, Properties> getSections() + { + return _sections; + } + +} diff --git a/qpid/java/broker-plugins/experimental/info/src/main/java/org/apache/qpid/info/util/SoapClient.java b/qpid/java/broker-plugins/experimental/info/src/main/java/org/apache/qpid/info/util/SoapClient.java new file mode 100644 index 0000000000..0f66085fc3 --- /dev/null +++ b/qpid/java/broker-plugins/experimental/info/src/main/java/org/apache/qpid/info/util/SoapClient.java @@ -0,0 +1,155 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +/** + * + * @author sorin + * + * An simple SOAP client for qpid info service + */ +package org.apache.qpid.info.util; + +import java.io.BufferedWriter; +import java.io.OutputStreamWriter; +import java.net.InetAddress; +import java.net.Socket; +import java.util.HashMap; +import java.util.Properties; + +public class SoapClient +{ + + private final StringBuffer _xmlData; + + private final Properties _destprops; + + private final String _hostname; + + private final int _port; + + private final String _urlpath; + + private final String _soapenvelope; + + private final String _soapaction; + + private final StringBuffer _soapMessage = new StringBuffer(); + + + public SoapClient(HashMap<String, String> map, Properties destprops) + { + _destprops = destprops; + _hostname = (String) _destprops.get("soap.hostname"); + _port = Integer.parseInt((String) _destprops.get("soap.port")); + _urlpath = (String) destprops.get("soap.path"); + _soapenvelope = (String) destprops.get("soap.envelope"); + _soapaction = (String) destprops.get("soap.action"); + _xmlData = new StringBuffer(_soapenvelope); + replaceVariables(map); + } + + public StringBuffer getXMLData() + { + return _xmlData; + } + + public StringBuffer getSoapMessage() { + return _soapMessage; + } + + public String getSoapEnvelope() { + return _soapenvelope; + } + + /** + * Clears and sets new XML data + * @param sb the new data to set + */ + public void setXMLData(StringBuffer sb) + { + _xmlData.delete(0, _xmlData.length()); + _xmlData.append(sb); + } + + + public void replaceVariables(HashMap<String, String> vars) + { + int ix = 0; + for (String var : vars.keySet()) + { + while ((ix = _xmlData.indexOf("@" + var.toUpperCase())) >= 0) + { + _xmlData.replace(ix, ix + 1 + var.length(), vars.get(var)); + } + } + } + + public void replaceVariables(Properties varProps) + { + if (varProps == null) + { + return; + } + int ix = 0; + for (Object var : varProps.keySet()) + { + while ((ix = _xmlData.indexOf("@" + var)) >= 0) + { + _xmlData.replace(ix, ix + 1 + var.toString().length(), varProps + .get(var).toString()); + } + } + } + + + public void sendSOAPMessage() + { + + try + { + InetAddress addr = InetAddress.getByName(_hostname); + Socket sock = new Socket(addr, _port); + StringBuffer sb = new StringBuffer(); + sb.append("POST " + _urlpath + " HTTP/1.1\r\n"); + sb.append("Host: " + _hostname + ":" + _port + "\r\n"); + sb.append("Content-Length: " + _xmlData.length() + "\r\n"); + sb.append("Content-Type: text/xml; charset=\"utf-8\"\r\n"); + sb.append("SOAPAction: \"urn:"+ _soapaction +"\"\r\n"); + sb.append("User-Agent: Axis2\r\n"); + sb.append("\r\n"); + // Send header + BufferedWriter wr = new BufferedWriter(new OutputStreamWriter(sock + .getOutputStream(), "UTF-8")); + synchronized(_soapMessage) { + _soapMessage.setLength(0); + _soapMessage.append(sb); + _soapMessage.append(_xmlData); + } + // Send data + wr.write(_soapMessage.toString()); + wr.flush(); + wr.close(); + + } catch (Exception ex) + { + // Drop any exception + } + } +} diff --git a/qpid/java/broker-plugins/experimental/info/src/main/java/org/apache/qpid/info/util/XMLWriter.java b/qpid/java/broker-plugins/experimental/info/src/main/java/org/apache/qpid/info/util/XMLWriter.java new file mode 100644 index 0000000000..a266edae00 --- /dev/null +++ b/qpid/java/broker-plugins/experimental/info/src/main/java/org/apache/qpid/info/util/XMLWriter.java @@ -0,0 +1,100 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +package org.apache.qpid.info.util; + +import java.util.Map; + +/** + * + * Naive and rudimentary XML writer + * It has methods to write the header, a tag with attributes + * and values. It escapes the XML special characters + */ +public class XMLWriter +{ + + private final StringBuffer _sb; + + private final String INDENT = " "; + + public XMLWriter(StringBuffer sb) + { + _sb = sb; + } + + public StringBuffer getXML() + { + return _sb; + } + + public void writeXMLHeader() + { + _sb.append("<?xml version=\"1.0\"?>\n"); + } + + public void writeTag(String tagName, Map<String, String> attributes, + String value) + { + writeOpenTag(tagName, attributes); + writeValue(value); + writeCloseTag(tagName); + } + + public void writeOpenTag(String tagName, Map<String, String> attributes) + { + _sb.append("<").append(tagName); + if (null == attributes) + { + _sb.append(">\n"); + return; + } + for (String key : attributes.keySet()) + { + _sb.append(" ").append(key + "=\"" + attributes.get(key) + "\""); + } + _sb.append(">\n"); + + } + + private void writeValue(String val) + { + _sb.append(INDENT).append(escapeXML(val) + "\n"); + } + + public void writeCloseTag(String tagName) + { + _sb.append("</" + tagName + ">\n"); + } + + private String escapeXML(String xmlStr) + { + if (null == xmlStr) + return null; + xmlStr = xmlStr.replaceAll("&", "&"); + xmlStr = xmlStr.replace("<", "<"); + xmlStr = xmlStr.replace(">", ">"); + xmlStr = xmlStr.replace("\"", """); + xmlStr = xmlStr.replace("'", "'"); + return xmlStr; + } + +} diff --git a/qpid/java/broker-plugins/experimental/info/src/test/java/org/apache/qpid/info/systest/InfoPluginTest.java b/qpid/java/broker-plugins/experimental/info/src/test/java/org/apache/qpid/info/systest/InfoPluginTest.java new file mode 100644 index 0000000000..156c9eb138 --- /dev/null +++ b/qpid/java/broker-plugins/experimental/info/src/test/java/org/apache/qpid/info/systest/InfoPluginTest.java @@ -0,0 +1,276 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.info.systest; + +import org.apache.qpid.test.utils.QpidBrokerTestCase; + +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.ServerSocket; +import java.net.Socket; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +public class InfoPluginTest extends QpidBrokerTestCase +{ + private String QPID_HOME = null; + + private ServerSocket _server = null; + + private int _port; + + private static final String CR = System.getProperty("line.separator"); + + private static final String FS = File.separator; + + private final String _cfgRelPath = "etc" + FS + "qpidinfo.ini"; + + private File _tmpCfgFile; + + private final String _soapEnvelopeHead = "<?xml version=\"1.0\"?><soap:Envelope xmlns:soap=\"http://www.w3.org/2001/12/soap-envelope\" soap:encodingStyle=\"http://www.w3.org/2001/12/soap-encoding\">"; + + private final String _soapEnvelopeTail = "</soap:Envelope>"; + + private String _soapMessage1 = "@ACTION" + "-" + "@VERSION"; + + private String _soapMessage2 = "@VERSION" + "-" + "@ACTION"; + + private CountDownLatch _latch = new CountDownLatch(2); + + final List<List<String>> _recv = new ArrayList<List<String>>(); + + Thread _socketAcceptor; + + public void setUp() throws Exception + { + QPID_HOME = System.getProperty("QPID_HOME"); + if (QPID_HOME != null) + { + System.out.println("QPID_HOME=" + QPID_HOME); + } + else + { + fail("QPID_HOME not set"); + } + + startSoapServer(); + // Must start the server first to identify a free port. + createConfigFile(); + } + + public void tearDown() throws Exception + { + System.out.println("*** Stopping socket server..."); + _socketAcceptor.join(2000); + + System.out.println("*** Deleting the config file..."); + if (_tmpCfgFile.isFile()) + { + _tmpCfgFile.delete(); + } + super.tearDown(); + } + + private void createConfigFile() + { + try + { + _tmpCfgFile = new File(QPID_HOME + FS + _cfgRelPath); + _tmpCfgFile.deleteOnExit(); + if (_tmpCfgFile.isFile()) + { + _tmpCfgFile.delete(); + } + assertTrue("Unable to create file.", _tmpCfgFile.createNewFile()); + assertTrue(_tmpCfgFile.isFile()); + FileWriter fwriter = new FileWriter(_tmpCfgFile); + BufferedWriter writer = new BufferedWriter(fwriter); + writer.write("protocol=soap"); + writer.write(CR); + writer.write("soap.hostname=localhost"); + writer.write(CR); + writer.write("soap.port=" + _port); + writer.write(CR); + writer.write(CR); + writer.write("[MSG1]"); + writer.write(CR); + writer.write("soap.path=/info1"); + writer.write(CR); + writer.write("soap.action=submitinfo1"); + writer.write(CR); + writer.write("soap.envelope=" + _soapEnvelopeHead + _soapMessage1 + + _soapEnvelopeTail); + writer.write(CR); + writer.write(CR); + writer.write("[MSG2]"); + writer.write(CR); + writer.write("soap.path=/info2"); + writer.write(CR); + writer.write("soap.action=submitinfo2"); + writer.write(CR); + writer.write("soap.envelope=" + _soapEnvelopeHead + _soapMessage2 + + _soapEnvelopeTail); + writer.write(CR); + writer.write(CR); + writer.close(); + assertTrue("Config file size is zero", _tmpCfgFile.length() > 0); + } + catch (IOException e) + { + fail("Unable to create the qpidinfo.properties due to: " + + e.getMessage()); + } + } + + private void startSoapServer() throws Exception + { + try + { + _server = new ServerSocket(0); + _port = _server.getLocalPort(); + assertTrue("Server not yet bound.", _port != -1); + + assertNotNull("SocketServer is null", _server); + } + catch (Exception ex) + { + fail("Unable to start the socket server due to: " + ex.getMessage()); + } + + _socketAcceptor = new Thread() + { + public void run() + { + while (true) + { + try + { + Socket socket = _server.accept(); + new ConnectionHandler(socket); + } + catch (IOException e) + { + fail("Error opening the socket in accept mode"); + } + } + } + }; + _socketAcceptor.start(); + System.out.println("*** Socket server started..."); + } + + class ConnectionHandler implements Runnable + { + private Socket _socket; + + public ConnectionHandler(Socket socket) + { + _socket = socket; + Thread t = new Thread(this); + t.start(); + } + + public void run() + { + System.out.println("*** Connection handler running..."); + List<String> buf = new ArrayList<String>(); + String line; + try + { + BufferedReader br = new BufferedReader(new InputStreamReader( + _socket.getInputStream())); + assertNotNull(br); + while ((line = br.readLine()) != null) + { + buf.add(line); + } + br.close(); + System.out.println("*** Received buffer: " + buf); + System.out.println("*** Latch countdown"); + _latch.countDown(); + synchronized (_recv) + { + _recv.add(buf); + } + } + catch (Exception ex) + { + ex.printStackTrace(); + fail("Exception while reading from the socket"); + } + + } + + } + + public void testInfoPlugin() throws Exception + { + //Start the broker + super.setUp(); + if (!_latch.await(10, TimeUnit.SECONDS)) + { + fail("Timeout awaiting for the latch, upon startup"); + } + + validateResponses("STARTUP"); + + _recv.clear(); + _latch = new CountDownLatch(2); + + stopBroker(); + + if (!_latch.await(10, TimeUnit.SECONDS)) + { + fail("Timeout awaiting for the latch, upon shutdown"); + } + + validateResponses("SHUTDOWN"); + + } + + /** + * Check the responses from the server to ensure they contain the required messages. + * @param action String to match for the SHUTDOWN or STARTUP action. + */ + private void validateResponses(String action) + { + assertTrue("Received less than 2 messages", _recv.size() > 1); + + // Message 1 + assertTrue("Message does not contain Host: localhost:" + _port + "\n" + _recv.get(0), _recv.get(0).contains("Host: localhost:" + _port)); + assertTrue("Message does not contain: User-Agent: Axis2 " + "\n" + _recv.get(0), _recv.get(0).contains("User-Agent: Axis2")); + assertTrue("Message does not contain: SOAPAction: \"urn:submitinfo\"" + "\n" + _recv.get(0).get(4), _recv.get(0).get(4).startsWith("SOAPAction: \"urn:submitinfo")); + assertTrue("Message does not contain '" + action + "' in the soap envelope" + "\n" + _recv.get(0).get(7), _recv.get(0).get(7).contains(action)); + + // Message 2 + assertTrue("Message does not contain Host: localhost:" + _port + "\n" + _recv.get(1), _recv.get(1).contains("Host: localhost:" + _port)); + assertTrue("Message does not contain: User-Agent: Axis2 " + "\n" + _recv.get(1), _recv.get(1).contains("User-Agent: Axis2")); + assertTrue("Message does not contain: SOAPAction: \"urn:submitinfo\"" + "\n" + _recv.get(1).get(4), _recv.get(1).get(4).startsWith("SOAPAction: \"urn:submitinfo")); + assertTrue("Message does not contain '" + action + "' in the soap envelope" + "\n" + _recv.get(1).get(7), _recv.get(1).get(7).contains(action)); + } + +} diff --git a/qpid/java/broker-plugins/experimental/info/src/test/java/org/apache/qpid/info/test/HttpPosterTest.java b/qpid/java/broker-plugins/experimental/info/src/test/java/org/apache/qpid/info/test/HttpPosterTest.java new file mode 100644 index 0000000000..4f76fea8ef --- /dev/null +++ b/qpid/java/broker-plugins/experimental/info/src/test/java/org/apache/qpid/info/test/HttpPosterTest.java @@ -0,0 +1,107 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.info.test; + +import java.util.List; +import java.util.Properties; + +import org.apache.qpid.info.util.HttpPoster; +import org.mortbay.jetty.testing.ServletTester; + +import junit.framework.TestCase; + +/* + * This test verifies that the plugin posts correctly to a webserver + * We use an embedded jetty container to mimic the webserver + */ +public class HttpPosterTest extends TestCase +{ + + private ServletTester tester; + + private String baseURL; + + private final String contextPath = "/info"; + + /* + * This method generates a dummy HttpPoster with a dummy body containing a + * single line. The url we are posting to can be controlled by the parameter + * url + * + * @param url + */ + private HttpPoster getHttpPoster(String url) + { + StringBuffer sb = new StringBuffer("test=TEST"); + Properties props = new Properties(); + props.put("http.url", url); + return new HttpPoster(props, sb); + } + + /* + * (non-Javadoc) + * + * @see junit.framework.TestCase#setUp() + */ + protected void setUp() throws Exception + { + tester = new ServletTester(); + tester.setContextPath("/"); + tester.addServlet(InfoServlet.class, contextPath); + baseURL = tester.createSocketConnector(true); + tester.start(); + } + + /* + * (non-Javadoc) + * + * @see junit.framework.TestCase#tearDown() + */ + protected void tearDown() throws Exception + { + super.tearDown(); + tester.stop(); + } + + /* + * This test is posting a string to an embedded Jetty Servlet and captures + * the response message. If the servlet receives the message ok, it will + * print Ok. A failure test is following where we post to a non-existent URL + */ + public void testHttpPoster() throws Exception + { + // Test HttpPoster posts correctly to the servlet + HttpPoster hp = getHttpPoster(baseURL + contextPath); + assertNotNull(hp); + hp.run(); + List<String> response = hp.get_response(); + assertTrue(response.size() > 0); + assertEquals("OK <br>", response.get(0).toString()); + + // Failure Test + hp = getHttpPoster("http://localhost/nonexistent"); + hp.run(); + response = hp.get_response(); + assertTrue(response.size() == 0); + + } + +} diff --git a/qpid/java/broker-plugins/experimental/info/src/test/java/org/apache/qpid/info/test/InfoServiceImplTest.java b/qpid/java/broker-plugins/experimental/info/src/test/java/org/apache/qpid/info/test/InfoServiceImplTest.java new file mode 100644 index 0000000000..9f359582a5 --- /dev/null +++ b/qpid/java/broker-plugins/experimental/info/src/test/java/org/apache/qpid/info/test/InfoServiceImplTest.java @@ -0,0 +1,63 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +package org.apache.qpid.info.test; + +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.Properties; + +import org.apache.qpid.info.Info; +import org.apache.qpid.info.InfoServiceImpl; + +import junit.framework.TestCase; + +/* + * This test verifies the invoke() method for the info service making sure that the parameters are returned + */ +public class InfoServiceImplTest extends TestCase +{ + + InfoServiceImpl _isi = null; + + @SuppressWarnings("unchecked") + public void testInvoke() + { + _isi = new InfoServiceImpl(); + assertNotNull(_isi); + Info<? extends Map<String, String>> info = (Info<? extends Map<String, String>>) _isi + .invoke("START"); + assertNotNull(info); + Properties props = info.toProps(); + assertNotNull(props); + List<String> infoProps = Arrays.asList("java.class.path", + "java.vm.name", "java.class.version", "os.arch", "os.name", + "os.version", "sun.arch.data.model", "user.dir", "user.name", + "user.timezone"); + for (String tag : infoProps) + { + assertNotNull("Info.toProps() does not have the property: " + tag, + props.getProperty(tag)); + } + } + +} diff --git a/qpid/java/broker-plugins/experimental/info/src/test/java/org/apache/qpid/info/test/InfoServlet.java b/qpid/java/broker-plugins/experimental/info/src/test/java/org/apache/qpid/info/test/InfoServlet.java new file mode 100644 index 0000000000..6b12a2d80c --- /dev/null +++ b/qpid/java/broker-plugins/experimental/info/src/test/java/org/apache/qpid/info/test/InfoServlet.java @@ -0,0 +1,57 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +package org.apache.qpid.info.test; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.PrintWriter; +import javax.servlet.GenericServlet; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; + +/* + * This is a servlet used by the embedded Jetty to be able to receive http post + * from the info plugin + */ + +public class InfoServlet extends GenericServlet +{ + private static final long serialVersionUID = 1L; + + @Override + public void service(ServletRequest request, ServletResponse response) + throws ServletException, IOException + { + String line; + BufferedReader in = request.getReader(); + while ((line = in.readLine()) != null) + { + System.out.println(line); + } + response.setContentType("text/html"); + PrintWriter out = response.getWriter(); + out.println("OK <br>\n"); + System.out.println("ServletResponse: OK"); + } + +}
\ No newline at end of file diff --git a/qpid/java/broker-plugins/experimental/info/src/test/java/org/apache/qpid/info/test/InfoTest.java b/qpid/java/broker-plugins/experimental/info/src/test/java/org/apache/qpid/info/test/InfoTest.java new file mode 100644 index 0000000000..bb4965ef1e --- /dev/null +++ b/qpid/java/broker-plugins/experimental/info/src/test/java/org/apache/qpid/info/test/InfoTest.java @@ -0,0 +1,112 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +package org.apache.qpid.info.test; + +import java.util.HashMap; +import java.util.Properties; +import junit.framework.TestCase; +import org.apache.qpid.info.Info; + +/* + * This test verifies the toString(), toProps(), toXML() and toStringBuffer() methods of the Info object + * + */ +public class InfoTest extends TestCase +{ + private HashMap<String, String> _infoPayLoad = null; + + private Info<HashMap<String, String>> _info = null; + + protected void setUp() throws Exception + { + super.setUp(); + _infoPayLoad = new HashMap<String, String>(); + _infoPayLoad.put("test", "Test"); + _info = new Info<HashMap<String, String>>(_infoPayLoad); + } + + /* + * Test the conversion toString() of the Info object + */ + public void testToString() + { + assertNotNull("toString() returned null", _info.toString()); + assertEquals("toString() did not return the proper string", + "test=Test\n", _info.toString()); + } + + /* + * Test the conversion toProps() of the Info object + */ + public void testToProps() + { + Properties props = new Properties(); + props.put("test", "Test"); + assertNotNull("toProperties() returned null", _info.toProps()); + assertEquals("toProperties not returned the proper object", props, _info + .toProps()); + } + + /* + * Test the conversion toStringBuffer() of the Info object + */ + public void testToStringBuffer() + { + StringBuffer sb = new StringBuffer("test=Test\n"); + assertNotNull(_info.toStringBuffer()); + assertEquals(sb.toString(), _info.toStringBuffer().toString()); + } + + /* + * Test conversion toXML() of the info object + */ + public void testToXML() + { + String INDENT = " "; + StringBuffer sb = new StringBuffer(); + sb.append("<?xml version=\"1.0\"?>\n"); + sb.append("<qpidinfo>\n"); + sb.append("<test>\n"); + sb.append(INDENT + "Test\n"); + sb.append("</test>\n"); + sb.append("</qpidinfo>\n"); + assertEquals("toString() does not return the proper string", _info + .toXML().toString(), sb.toString()); + } + + /* + * Test the conversion toMap() of the Info object + */ + public void testToMap() + { + HashMap<String, String> thm = _info.toMap(); + assertFalse("toMap() returned empty map", thm.isEmpty()); + assertEquals("testToMap did not returned 1", 1, thm.size()); + assertTrue("toMap() returned a map not containing expected key: test", + thm.containsKey("test")); + assertTrue( + "toMap() returned a map not containing the value for key test: Test", + thm.containsValue("Test")); + + } + +} diff --git a/qpid/java/broker-plugins/experimental/info/src/test/java/org/apache/qpid/info/test/IniFileReaderTest.java b/qpid/java/broker-plugins/experimental/info/src/test/java/org/apache/qpid/info/test/IniFileReaderTest.java new file mode 100644 index 0000000000..77ecaa2176 --- /dev/null +++ b/qpid/java/broker-plugins/experimental/info/src/test/java/org/apache/qpid/info/test/IniFileReaderTest.java @@ -0,0 +1,136 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +package org.apache.qpid.info.test; + +import junit.framework.TestCase; +import org.apache.qpid.info.util.IniFileReader; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.util.Map; +import java.util.Properties; + +/** + * Test the Loading of the ini file reader by first writing + * out a correct ini file. + */ +public class IniFileReaderTest extends TestCase +{ + + public void testLoad() + { + IniFileReader ifr = new IniFileReader(); + File iniFile = null; + try + { + iniFile = File.createTempFile("temp", "ini"); + iniFile.deleteOnExit(); + BufferedWriter writer = new BufferedWriter(new FileWriter(iniFile)); + writer.write("# Global Comment1\n"); + writer.write("globalprop1=globalval1\n"); + writer.write("globalprop2=globalval2\n"); + writer.write("\n"); + writer.write("[Section1] # Comment on Section\n"); + writer.write("key1=val1 # Comment on Value\n"); + writer.write("key2=val2\n"); + writer.write("\n"); + writer.write("#Section2 Comment\n"); + writer.write("[Section2]\n"); + writer.write("key3=val3\n"); + writer.write("key4=val4\n"); + writer.write("key5=val5\n"); + writer.write("\n"); + writer.write("[Section3]\n"); + writer.write("key6=val6\n"); + writer.write("key7=val7\n"); + writer.write("\n"); + writer.close(); + } + catch (IOException e) + { + e.printStackTrace(); + fail("Unable to create temporary File"); + } + ifr.load(iniFile.getAbsolutePath()); + Map<String, Properties> sections = ifr.getSections(); + assertNotNull("Sections not null", sections); + assertEquals("Have 4 sections", sections.keySet().size(), 4); + assertTrue("Get globalprop1", sections.get("").getProperty("globalprop1").equals("globalval1")); + assertTrue("Get globalprop2", sections.get("").getProperty("globalprop2").equals("globalval2")); + assertNotNull("Section1 not null", sections.get("Section1")); + assertEquals("Section1 has 2 properties", sections.get("Section1").size(), 2); + assertTrue("Section1 key1 has val1", sections.get("Section1").getProperty("key1").equals("val1")); + assertTrue("Section1 key2 has val2", sections.get("Section1").getProperty("key2").equals("val2")); + assertEquals("Section2 has 3 properties", sections.get("Section2").size(), 3); + assertTrue("Section2 key3 has val3", sections.get("Section2").getProperty("key3").equals("val3")); + assertTrue("Section2 key4 has val4", sections.get("Section2").getProperty("key4").equals("val4")); + assertTrue("Section2 key5 has val5", sections.get("Section2").getProperty("key5").equals("val5")); + assertEquals("Section3 has 2 properties", sections.get("Section3").size(), 2); + assertTrue("Section3 key6 has val6", sections.get("Section3").getProperty("key6").equals("val6")); + assertTrue("Section3 key7 has val7", sections.get("Section3").getProperty("key7").equals("val7")); + } + + /** + * Test to ensure that the loading of a file with an unclosed section header + * fails to parse. + * + * Section needs to be fully enclosed in square brackets '[<name>]' + */ + public void testIncompleteSection1Load() + { + IniFileReader ifr = new IniFileReader(); + File iniFile = null; + try + { + iniFile = File.createTempFile(getName(), "ini"); + iniFile.deleteOnExit(); + BufferedWriter writer = new BufferedWriter(new FileWriter(iniFile)); + writer.write("# Global Comment1\n"); + writer.write("globalprop1=globalval1\n"); + writer.write("globalprop2=globalval2\n"); + writer.write("\n"); + writer.write("[Section1\n"); // Note '[Section1' not complete + writer.write("key1=val1\n"); + writer.write("key2=val2\n"); + writer.write("\n"); + writer.close(); + } + catch (IOException e) + { + e.printStackTrace(); + fail("Unable to create temporary File"); + } + try + { + ifr.load(iniFile.getAbsolutePath()); + fail("File should fail to parse"); + } + catch (IllegalArgumentException iae) + { + assertEquals("Incorrect Exception", "Section1 is not closed", iae.getMessage()); + } + + } + +} diff --git a/qpid/java/broker-plugins/experimental/info/src/test/java/org/apache/qpid/info/test/SoapClientTest.java b/qpid/java/broker-plugins/experimental/info/src/test/java/org/apache/qpid/info/test/SoapClientTest.java new file mode 100644 index 0000000000..a3d993a39f --- /dev/null +++ b/qpid/java/broker-plugins/experimental/info/src/test/java/org/apache/qpid/info/test/SoapClientTest.java @@ -0,0 +1,208 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +package org.apache.qpid.info.test; + +import junit.framework.TestCase; +import org.apache.qpid.info.util.SoapClient; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.ServerSocket; +import java.net.Socket; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Properties; + +public class SoapClientTest extends TestCase +{ + + private int _port; + + private final String _hostName = "localhost"; + + private final String _urlPath = "/testSoap"; + + private ServerSocket _server = null; + + /* + * Generate a soap client from a custom URL, hostname, port and soap context + * path to be derived + */ + private SoapClient getSoapClient() + { + Properties destprops = new Properties(); + destprops.setProperty("soap.hostname", _hostName); + destprops.setProperty("soap.port", _port + ""); + destprops.setProperty("soap.urlpath", _urlPath); + destprops.setProperty("soap.envelope", "<ip>@IP</ip>"); + destprops.setProperty("soap.action", "send"); + HashMap<String, String> soapmap = new HashMap<String, String>(); + soapmap.put("IP", "127.0.0.1"); + return new SoapClient(soapmap, destprops); + } + + /* + * A connection handler class that verifies the correct message is received + * + */ + class ConnectionHandler implements Runnable + { + private Socket socket; + + public ConnectionHandler(Socket socket) + { + this.socket = socket; + Thread t = new Thread(this); + t.start(); + } + + public void run() + { + String line; + final List<String> response = new ArrayList<String>(); + try + { + BufferedReader br = new BufferedReader(new InputStreamReader( + socket.getInputStream())); + assertNotNull(br); + while ((line = br.readLine()) != null) + { + response.add(line); + } + br.close(); + } + catch (Exception ex) + { + ex.printStackTrace(); + fail("Exception while reading from the socket"); + } + assertTrue(response.contains("<ip>127.0.0.1</ip>")); + assertTrue(response.contains("SOAPAction: \"urn:send\"")); + assertTrue(response + .contains("Content-Type: text/xml; charset=\"utf-8\"")); + assertTrue(response.contains("Host: localhost" + _port)); + assertTrue(response.contains("User-Agent: Axis2")); + } + + } + + /* + * Test that the SOAP client sends the expected data to the socket We mock a + * simple SOAP envelope: <ip>127.0.0.1</ip> + */ + public void testSoapClient() throws Exception + { + // + try + { + _server = new ServerSocket(0); + _port = _server.getLocalPort(); + assertTrue("Server is not yet bound to a port", _port != -1); + assertNotNull(_server); + } + catch (Exception ex) + { + ex.printStackTrace(); + fail("Unable to start the socket server"); + } + + Thread _socketAcceptor = new Thread() + { + public void run() + { + try + { + Socket socket = _server.accept(); + new ConnectionHandler(socket); + } + catch (IOException e) + { + e.printStackTrace(); + } + } + }; + _socketAcceptor.start(); + // Sleep for 1 second to allow the ServerSocket readiness + Thread.sleep(1000); + SoapClient sc = getSoapClient(); + assertNotNull(sc); + sc.sendSOAPMessage(); + + _socketAcceptor.join(2000); + + assertFalse("Socket Acceptor not stopped.", _socketAcceptor.isAlive()); + } + + /** + * Test SoapClient correctly clears previously set values + */ + public void testSoapClientXMLData() + { + SoapClient sc = getSoapClient(); + + StringBuffer initial = new StringBuffer("Initial Value"); + + sc.setXMLData(initial); + + assertEquals("getXMLData is not set with initial value", + initial.toString(), sc.getXMLData().toString()); + + + StringBuffer sb = new StringBuffer("<?xml version=\"1.0\"?><ip=@IP><port=@PORT>"); + sc.setXMLData(sb); + assertEquals(sc.getXMLData().length(), sb.length()); + assertEquals("getXMLData does not return the same StringBuffer set by setXMLData", + sb.toString(), sc.getXMLData().toString()); + } + + /** + * Test that variable replacement is performed on the soap.envelope. + * Create dummy soap message and validate that the variable have been replaced. + */ + public void testReplaceVariablesMap() + { + Properties props = new Properties(); + // Add dummy values as required to create a soap message + props.setProperty("soap.hostname", _hostName); + props.setProperty("soap.port", "0"); + props.setProperty("soap.urlpath", _urlPath); + props.setProperty("soap.action", "send"); + + /// The envelope is what we care about + props.setProperty("soap.envelope", "<addr>@IP:@PORT</addr>"); + HashMap<String, String> soapmap = new HashMap<String, String>(); + + /// Variables that should be replaced. + final String ip = "127.0.0.1"; + soapmap.put("IP", ip); + final String port = "8080"; + soapmap.put("PORT", port); + + SoapClient sc = new SoapClient(soapmap, props); + assertNotNull("SoapClient is null", sc); + + assertTrue("Replace variables did not work as expected", ("<addr>" + ip + ":" + port + "</addr>").equals(sc.getXMLData().toString())); + } + +} diff --git a/qpid/java/broker-plugins/experimental/info/src/test/java/org/apache/qpid/info/test/SystemInfoTest.java b/qpid/java/broker-plugins/experimental/info/src/test/java/org/apache/qpid/info/test/SystemInfoTest.java new file mode 100644 index 0000000000..6cb8e3a90a --- /dev/null +++ b/qpid/java/broker-plugins/experimental/info/src/test/java/org/apache/qpid/info/test/SystemInfoTest.java @@ -0,0 +1,56 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +package org.apache.qpid.info.test; + +import junit.framework.TestCase; +import org.apache.qpid.info.SystemInfo; + +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +/** Test the SystemInfo component */ +public class SystemInfoTest extends TestCase +{ + + /** + * Ensure the list of required properties are returned by the + * SystemInfo.getInfo call + */ + public void testGetInfo() + { + Map<String, String> sysInfoMap = SystemInfo.getInfo(); + assertNotNull("SystemInfo.getInfo() returned null", sysInfoMap); + List<String> sysInfoProps = Arrays.asList( + "java.class.path", + "java.vm.name", "java.class.version", "os.arch", "os.name", + "os.version", "sun.arch.data.model", "user.dir", "user.name", + "user.timezone", "hostname", "ip", "CPUCores", "Maximum_Memory", + "Free_Memory"); + + for (String tag : sysInfoProps) + { + assertNotNull("Map does not contain the tag: " + tag, sysInfoMap.get(tag)); + } + } + +}
\ No newline at end of file diff --git a/qpid/java/broker-plugins/experimental/info/src/test/java/org/apache/qpid/info/test/XMLWriterTest.java b/qpid/java/broker-plugins/experimental/info/src/test/java/org/apache/qpid/info/test/XMLWriterTest.java new file mode 100644 index 0000000000..f352226361 --- /dev/null +++ b/qpid/java/broker-plugins/experimental/info/src/test/java/org/apache/qpid/info/test/XMLWriterTest.java @@ -0,0 +1,132 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +package org.apache.qpid.info.test; + +import junit.framework.TestCase; +import org.apache.qpid.info.util.XMLWriter; + +import java.util.HashMap; + +/* + * This test verifies the XML writer custom class operations + */ + +public class XMLWriterTest extends TestCase +{ + + private XMLWriter xw = null; + + /** Test constructor arg is returned via getXML() */ + public void testXMLWriter() + { + StringBuffer input = new StringBuffer("Test"); + xw = new XMLWriter(input); + assertNotNull("XMLWriter could not instantiate", xw); + assertEquals("XMLWriter.getXML() failed", input, xw.getXML()); + } + + /** Test header generation */ + public void testWriteXMLHeader() + { + xw = new XMLWriter(new StringBuffer()); + assertNotNull(xw); + xw.writeXMLHeader(); + assertEquals("XMLWriter.writeXMLHeader(...) failed", "<?xml version=\"1.0\"?>\n", xw.getXML().toString()); + } + + /** Test tag created and written correctly */ + public void testWriteTag() + { + String INDENT = " "; + xw = new XMLWriter(new StringBuffer()); + assertNotNull("XMLWriter could not instantiate", xw); + xw.writeTag("test", new HashMap<String, String>(), "TEST"); + assertEquals("XMLWriter.writeTag(...) failed", "<test>\n" + INDENT + "TEST\n" + "</test>\n", xw.getXML() + .toString()); + } + + /** Test tag created and written correctly */ + public void testWriteTagWithNullAttribute() + { + String INDENT = " "; + xw = new XMLWriter(new StringBuffer()); + assertNotNull("XMLWriter could not instantiate", xw); + xw.writeTag("test", null, "TEST"); + assertEquals("XMLWriter.writeTag(...) failed", "<test>\n" + INDENT + "TEST\n" + "</test>\n", xw.getXML() + .toString()); + } + + /** Test tag created and written correctly with attribute */ + public void testWriteTagWithAttribute() + { + String INDENT = " "; + xw = new XMLWriter(new StringBuffer()); + assertNotNull("XMLWriter could not instantiate", xw); + HashMap<String, String> attr = new HashMap<String, String>(); + attr.put("id", "1"); + + xw.writeTag("test", attr, "TEST"); + assertEquals("XMLWriter.writeTag(...) failed", "<test id=\"1\">\n" + INDENT + "TEST\n" + "</test>\n", xw.getXML() + .toString()); + } + + /** Test open tag with an empty attribute map. Just creates an open tag */ + public void testWriteOpenTag() + { + xw = new XMLWriter(new StringBuffer()); + assertNotNull(xw); + HashMap<String, String> attr = new HashMap<String, String>(); + xw.writeOpenTag("test", attr); + assertEquals("XMLWriter.writeOpenTag(...) failed", "<test>\n", xw.getXML().toString()); + } + + /** Test open tag with a null attribute map. Just creates an open tag */ + public void testNullAtrributeOnTag() + { + xw = new XMLWriter(new StringBuffer()); + assertNotNull(xw); + xw.writeOpenTag("test", null); + assertEquals("XMLWriter.writeOpenTag(...) failed", "<test>\n", xw.getXML().toString()); + } + + /** Test that setting an attribute value on the tag is correctly outputted. */ + public void testAtrributeOnTag() + { + xw = new XMLWriter(new StringBuffer()); + assertNotNull(xw); + HashMap<String, String> attr = new HashMap<String, String>(); + + attr.put("id", "1"); + xw.writeOpenTag("test1", attr); + assertEquals("XMLWriter.writeOpenTag(...) failed", "<test1 id=\"1\">\n", xw.getXML().toString()); + } + + /** Test Close Tag is correctly written */ + public void testWriteCloseTag() + { + xw = new XMLWriter(new StringBuffer()); + assertNotNull(xw); + xw.writeCloseTag("test"); + assertEquals("</test>\n", xw.getXML().toString()); + } + +} diff --git a/qpid/java/broker-plugins/experimental/shutdown/MANIFEST.MF b/qpid/java/broker-plugins/experimental/shutdown/MANIFEST.MF new file mode 100644 index 0000000000..49e90c6aad --- /dev/null +++ b/qpid/java/broker-plugins/experimental/shutdown/MANIFEST.MF @@ -0,0 +1,15 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: Experimental Shutdown +Bundle-Description: Experimental Qpid Broker Shutdown Plugin +Bundle-License: http://www.apache.org/licenses/LICENSE-2.0.txt +Bundle-DocURL: http://qpid.apache.org/ +Bundle-SymbolicName: broker-plugins-experimental-shutdown;singleton:=true +Bundle-Version: 1.0.0 +Bundle-Activator: org.apache.qpid.shutdown.Activator +Import-Package: javax.management;resolution:=optional, + org.apache.log4j, + org.osgi.framework +Bundle-RequiredExecutionEnvironment: J2SE-1.5 +Bundle-ActivationPolicy: lazy + diff --git a/qpid/java/broker-plugins/experimental/shutdown/build.xml b/qpid/java/broker-plugins/experimental/shutdown/build.xml new file mode 100644 index 0000000000..ec4fce374e --- /dev/null +++ b/qpid/java/broker-plugins/experimental/shutdown/build.xml @@ -0,0 +1,32 @@ +<!-- + - + - Licensed to the Apache Software Foundation (ASF) under one + - or more contributor license agreements. See the NOTICE file + - distributed with this work for additional information + - regarding copyright ownership. The ASF licenses this file + - to you under the Apache License, Version 2.0 (the + - "License"); you may not use this file except in compliance + - with the License. You may obtain a copy of the License at + - + - http://www.apache.org/licenses/LICENSE-2.0 + - + - Unless required by applicable law or agreed to in writing, + - software distributed under the License is distributed on an + - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + - KIND, either express or implied. See the License for the + - specific language governing permissions and limitations + - under the License. + - + --> +<project name="AMQ Broker Shutdown Plugin" default="build"> + + <property name="module.depends" value="common broker broker-plugins"/> + <property name="module.test.depends" value="test broker/test management/common client systests"/> + <property name="module.manifest" value="MANIFEST.MF"/> + <property name="module.plugin" value="true"/> + + <import file="../../../module.xml"/> + + <target name="bundle" depends="bundle-tasks"/> + +</project> diff --git a/qpid/java/broker-plugins/experimental/shutdown/src/main/java/org/apache/qpid/shutdown/Activator.java b/qpid/java/broker-plugins/experimental/shutdown/src/main/java/org/apache/qpid/shutdown/Activator.java new file mode 100644 index 0000000000..ad5e7707b6 --- /dev/null +++ b/qpid/java/broker-plugins/experimental/shutdown/src/main/java/org/apache/qpid/shutdown/Activator.java @@ -0,0 +1,71 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.shutdown; + +import java.lang.management.ManagementFactory; + +import javax.management.InstanceNotFoundException; +import javax.management.MBeanServer; +import javax.management.ObjectName; + +import org.apache.log4j.Logger; +import org.osgi.framework.BundleActivator; +import org.osgi.framework.BundleContext; + +public class Activator implements BundleActivator +{ + private static final Logger _logger = Logger.getLogger(Activator.class); + + private static final String SHUTDOWN_MBEAN_NAME = "org.apache.qpid:type=ShutdownMBean"; + + /** @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext) */ + public void start(BundleContext ctx) throws Exception { + Shutdown shutdown = new Shutdown(); + if (ctx != null) + { + ctx.registerService(ShutdownMBean.class.getName(), shutdown, null); + } + + // MBean registration + MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); + ObjectName name = new ObjectName(SHUTDOWN_MBEAN_NAME); + mbs.registerMBean(shutdown, name); + + _logger.info("Shutdown plugin MBean registered"); + } + + /** @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext) */ + public void stop(BundleContext ctx) throws Exception + { + // Unregister MBean + MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); + ObjectName name = new ObjectName(SHUTDOWN_MBEAN_NAME); + try + { + mbs.unregisterMBean(name); + } + catch (InstanceNotFoundException e) + { + //ignore + } + + _logger.info("Shutdown plugin MBean unregistered"); + } +} diff --git a/qpid/java/broker-plugins/experimental/shutdown/src/main/java/org/apache/qpid/shutdown/Shutdown.java b/qpid/java/broker-plugins/experimental/shutdown/src/main/java/org/apache/qpid/shutdown/Shutdown.java new file mode 100644 index 0000000000..9a6f85fe9c --- /dev/null +++ b/qpid/java/broker-plugins/experimental/shutdown/src/main/java/org/apache/qpid/shutdown/Shutdown.java @@ -0,0 +1,104 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.shutdown; + +import java.text.DateFormat; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +import org.apache.log4j.Logger; + +/** + * Implementation of the JMX broker shutdown plugin. + */ +public class Shutdown implements ShutdownMBean +{ + private static final Logger _logger = Logger.getLogger(Shutdown.class); + + private static final String FORMAT = "yyyyy/MM/dd hh:mm:ss"; + private static final int THREAD_COUNT = 1; + private static final ScheduledExecutorService EXECUTOR = new ScheduledThreadPoolExecutor(THREAD_COUNT); + + private final Runnable _shutdown = new SystemExiter(); + + /** @see ShutdownMBean#shutdown() */ + public void shutdown() + { + _logger.info("Shutting down at user's request"); + shutdownBroker(0); + } + + /** @see ShutdownMBean#shutdown(long) */ + public void shutdown(long delay) + { + _logger.info("Scheduled broker shutdown after " + delay + "ms"); + shutdownBroker(delay); + } + + /** @see ShutdownMBean#shutdownAt(String) */ + public void shutdownAt(String when) + { + Date date; + DateFormat df = new SimpleDateFormat(FORMAT); + try + { + date = df.parse(when); + } + catch (ParseException e) + { + _logger.error("Invalid date \"" + when + "\": expecting " + FORMAT, e); + return; + } + _logger.info("Scheduled broker shutdown at " + when); + long now = System.currentTimeMillis(); + long time = date.getTime(); + if (time > now) + { + shutdownBroker(time - now); + } + else + { + shutdownBroker(0); + } + } + + /** + * Submits the {@link SystemExiter} job to shutdown the broker. + */ + private void shutdownBroker(long delay) + { + EXECUTOR.schedule(_shutdown, delay, TimeUnit.MILLISECONDS); + } + + /** + * Shutting down the system in another thread to avoid JMX exceptions being thrown. + */ + class SystemExiter implements Runnable + { + public void run() + { + System.exit(0); + } + } +} diff --git a/qpid/java/broker-plugins/experimental/shutdown/src/main/java/org/apache/qpid/shutdown/ShutdownMBean.java b/qpid/java/broker-plugins/experimental/shutdown/src/main/java/org/apache/qpid/shutdown/ShutdownMBean.java new file mode 100644 index 0000000000..6294f869e9 --- /dev/null +++ b/qpid/java/broker-plugins/experimental/shutdown/src/main/java/org/apache/qpid/shutdown/ShutdownMBean.java @@ -0,0 +1,47 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.shutdown; + +/** + * Shutdown plugin JMX MBean interface. + * + * Shuts the Qpid broker down via JMX. + */ +public interface ShutdownMBean +{ + /** + * Broker will be shut down immediately. + */ + public void shutdown(); + + /** + * Broker will be shutdown after the specified delay + * + * @param delay the number of ms to wait + */ + public void shutdown(long delay); + + /** + * Broker will be shutdown at the specified date and time. + * + * @param when the date and time to shutdown + */ + public void shutdownAt(String when); +} diff --git a/qpid/java/broker-plugins/experimental/shutdown/src/main/java/shutdown.bnd b/qpid/java/broker-plugins/experimental/shutdown/src/main/java/shutdown.bnd new file mode 100755 index 0000000000..f49578ba8c --- /dev/null +++ b/qpid/java/broker-plugins/experimental/shutdown/src/main/java/shutdown.bnd @@ -0,0 +1,25 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +ver: 0.11.0 + +Bundle-SymbolicName: qpid-shutdown-plugin +Bundle-Version: ${ver} +Export-Package: *;version=${ver} +Bundle-RequiredExecutionEnvironment: J2SE-1.5 |