You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by rg...@apache.org on 2015/11/25 00:24:30 UTC
svn commit: r1716277 - in /qpid/java/trunk:
broker-core/src/main/java/org/apache/qpid/server/model/
broker-core/src/main/java/org/apache/qpid/server/security/
broker-plugins/management-http/src/main/java/resources/js/qpid/management/store/managedcertif...
Author: rgodfrey
Date: Tue Nov 24 23:24:30 2015
New Revision: 1716277
URL: http://svn.apache.org/viewvc?rev=1716277&view=rev
Log:
QPID-6906 : Allow for better management of ManagedPeerCertificateTrustStores
Added:
qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/CertificateDetails.java (with props)
qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/ManagedPeerCertificateTrustStoreImpl.java
- copied, changed from r1715537, qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/ManagedPeerCertificateTrustsStoreImpl.java
qpid/java/trunk/broker-plugins/management-http/src/main/java/resources/js/qpid/management/store/managedcertificatestore/
qpid/java/trunk/broker-plugins/management-http/src/main/java/resources/js/qpid/management/store/managedcertificatestore/show.js
- copied, changed from r1715537, qpid/java/trunk/broker-plugins/management-http/src/main/java/resources/js/qpid/management/store/sitespecifictruststore/show.js
qpid/java/trunk/broker-plugins/management-http/src/main/java/resources/store/managedcertificatestore/
qpid/java/trunk/broker-plugins/management-http/src/main/java/resources/store/managedcertificatestore/show.html
- copied, changed from r1715537, qpid/java/trunk/broker-plugins/management-http/src/main/java/resources/store/sitespecifictruststore/show.html
Removed:
qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/ManagedPeerCertificateTrustsStoreImpl.java
Modified:
qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/AttributeValueConverter.java
qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/ManagedPeerCertificateTrustStore.java
Modified: qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/AttributeValueConverter.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/AttributeValueConverter.java?rev=1716277&r1=1716276&r2=1716277&view=diff
==============================================================================
--- qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/AttributeValueConverter.java (original)
+++ qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/AttributeValueConverter.java Tue Nov 24 23:24:30 2015
@@ -128,10 +128,11 @@ abstract class AttributeValueConverter<T
};
-
-
static final AttributeValueConverter<Certificate> CERTIFICATE_CONVERTER = new AttributeValueConverter<Certificate>()
{
+ private static final String BEGIN_CERTIFICATE = "-----BEGIN CERTIFICATE-----\n";
+ private static final String END_CERTIFICATE = "\n-----END CERTIFICATE-----";
+
private final CertificateFactory _certFactory;
{
@@ -164,7 +165,17 @@ abstract class AttributeValueConverter<T
}
else if(value instanceof String)
{
- return convert(BINARY_CONVERTER.convert(AbstractConfiguredObject.interpolate(object, (String) value),object),object);
+ String strValue = AbstractConfiguredObject.interpolate(object, (String) value);
+ if(strValue.contains(BEGIN_CERTIFICATE))
+ {
+ strValue = strValue.substring(strValue.indexOf(BEGIN_CERTIFICATE) + BEGIN_CERTIFICATE.length());
+ if(strValue.contains(END_CERTIFICATE))
+ {
+ strValue = strValue.substring(0,strValue.indexOf(END_CERTIFICATE));
+ }
+ strValue = strValue.replaceAll("\\s","");
+ }
+ return convert(BINARY_CONVERTER.convert(strValue, object),object);
}
else if(value == null)
{
Added: qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/CertificateDetails.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/CertificateDetails.java?rev=1716277&view=auto
==============================================================================
--- qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/CertificateDetails.java (added)
+++ qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/CertificateDetails.java Tue Nov 24 23:24:30 2015
@@ -0,0 +1,41 @@
+/*
+ *
+ * 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.server.security;
+
+import java.util.Date;
+import java.util.List;
+
+import org.apache.qpid.server.model.ManagedAttributeValue;
+import org.apache.qpid.server.model.ManagedAttributeValueType;
+
+@ManagedAttributeValueType
+public interface CertificateDetails extends ManagedAttributeValue
+{
+ String getSerialNumber();
+ int getVersion();
+ String getSignatureAlgorithm();
+ String getIssuerName();
+ String getSubjectName();
+ List<String> getSubjectAltNames();
+ long getValidFrom();
+ long getValidUntil();
+
+}
Propchange: qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/CertificateDetails.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/ManagedPeerCertificateTrustStore.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/ManagedPeerCertificateTrustStore.java?rev=1716277&r1=1716276&r2=1716277&view=diff
==============================================================================
--- qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/ManagedPeerCertificateTrustStore.java (original)
+++ qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/ManagedPeerCertificateTrustStore.java Tue Nov 24 23:24:30 2015
@@ -23,8 +23,11 @@ package org.apache.qpid.server.security;
import java.security.cert.Certificate;
import java.util.List;
+import org.apache.qpid.server.model.DerivedAttribute;
import org.apache.qpid.server.model.ManagedAttribute;
import org.apache.qpid.server.model.ManagedObject;
+import org.apache.qpid.server.model.ManagedOperation;
+import org.apache.qpid.server.model.Param;
import org.apache.qpid.server.model.TrustStore;
@ManagedObject( category = false, type = ManagedPeerCertificateTrustStore.TYPE_NAME)
@@ -40,7 +43,12 @@ public interface ManagedPeerCertificateT
@ManagedAttribute( oversize = true, defaultValue = "[]" )
List<Certificate> getStoredCertificates();
- void addCertificate(Certificate cert);
+ @ManagedOperation
+ void addCertificate(@Param(name="certificate") Certificate certificate);
+ @DerivedAttribute
+ List<CertificateDetails> getCertificateDetails();
+ @ManagedOperation
+ void removeCertificates(@Param(name="certificates") List<CertificateDetails> certificates);
}
Copied: qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/ManagedPeerCertificateTrustStoreImpl.java (from r1715537, qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/ManagedPeerCertificateTrustsStoreImpl.java)
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/ManagedPeerCertificateTrustStoreImpl.java?p2=qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/ManagedPeerCertificateTrustStoreImpl.java&p1=qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/ManagedPeerCertificateTrustsStoreImpl.java&r1=1715537&r2=1716277&rev=1716277&view=diff
==============================================================================
--- qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/ManagedPeerCertificateTrustsStoreImpl.java (original)
+++ qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/security/ManagedPeerCertificateTrustStoreImpl.java Tue Nov 24 23:24:30 2015
@@ -21,15 +21,24 @@
package org.apache.qpid.server.security;
import java.io.IOException;
+import java.math.BigInteger;
import java.security.GeneralSecurityException;
import java.security.cert.Certificate;
+import java.security.cert.CertificateParsingException;
+import java.security.cert.X509Certificate;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.Collections;
+import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.TimeZone;
import java.util.concurrent.Callable;
import javax.net.ssl.TrustManager;
@@ -51,6 +60,7 @@ import org.apache.qpid.server.model.Brok
import org.apache.qpid.server.model.ConfiguredObject;
import org.apache.qpid.server.model.IntegrityViolationException;
import org.apache.qpid.server.model.ManagedAttributeField;
+import org.apache.qpid.server.model.ManagedAttributeValue;
import org.apache.qpid.server.model.ManagedObject;
import org.apache.qpid.server.model.ManagedObjectFactoryConstructor;
import org.apache.qpid.server.model.Port;
@@ -63,10 +73,10 @@ import org.apache.qpid.transport.network
import org.apache.qpid.transport.network.security.ssl.QpidPeersOnlyTrustManager;
@ManagedObject( category = false )
-public class ManagedPeerCertificateTrustsStoreImpl
- extends AbstractConfiguredObject<ManagedPeerCertificateTrustsStoreImpl> implements ManagedPeerCertificateTrustStore<ManagedPeerCertificateTrustsStoreImpl>
+public class ManagedPeerCertificateTrustStoreImpl
+ extends AbstractConfiguredObject<ManagedPeerCertificateTrustStoreImpl> implements ManagedPeerCertificateTrustStore<ManagedPeerCertificateTrustStoreImpl>
{
- private static final Logger LOGGER = LoggerFactory.getLogger(ManagedPeerCertificateTrustsStoreImpl.class);
+ private static final Logger LOGGER = LoggerFactory.getLogger(ManagedPeerCertificateTrustStoreImpl.class);
private final Broker<?> _broker;
private final EventLogger _eventLogger;
@@ -84,7 +94,7 @@ public class ManagedPeerCertificateTrust
private final List<Certificate> _storedCertificates = new ArrayList<>();
@ManagedObjectFactoryConstructor
- public ManagedPeerCertificateTrustsStoreImpl(final Map<String, Object> attributes, Broker<?> broker)
+ public ManagedPeerCertificateTrustStoreImpl(final Map<String, Object> attributes, Broker<?> broker)
{
super(parentsMap(broker), attributes);
_broker = broker;
@@ -274,7 +284,7 @@ public class ManagedPeerCertificateTrust
@Override
public String getObject()
{
- return ManagedPeerCertificateTrustsStoreImpl.this.toString();
+ return ManagedPeerCertificateTrustStoreImpl.this.toString();
}
@Override
@@ -307,4 +317,183 @@ public class ManagedPeerCertificateTrust
});
}
+
+ @Override
+ public List<CertificateDetails> getCertificateDetails()
+ {
+ List<CertificateDetails> details = new ArrayList<>();
+ for(Certificate cert : _storedCertificates)
+ {
+ if(cert instanceof X509Certificate)
+ {
+ details.add(new CertificateDetailsImpl((X509Certificate)cert));
+ }
+ }
+ return details;
+ }
+
+
+ @Override
+ public void removeCertificates(final List<CertificateDetails> certs)
+ {
+ final Map<String,Set<BigInteger>> certsToRemove = new HashMap<>();
+ for(CertificateDetails cert : certs)
+ {
+ if(!certsToRemove.containsKey(cert.getIssuerName()))
+ {
+ certsToRemove.put(cert.getIssuerName(), new HashSet<BigInteger>());
+ }
+ certsToRemove.get(cert.getIssuerName()).add(new BigInteger(cert.getSerialNumber()));
+ }
+
+ final Map<String, Object> updateMap = new HashMap<>();
+
+ doAfter(doOnConfigThread(new Task<ListenableFuture<Void>, RuntimeException>()
+ {
+ @Override
+ public ListenableFuture<Void> execute()
+ {
+
+ Set<Certificate> certs = new HashSet<>(_storedCertificates);
+
+ boolean updated = false;
+ Iterator<Certificate> iter = certs.iterator();
+ while(iter.hasNext())
+ {
+ Certificate cert = iter.next();
+ if(cert instanceof X509Certificate)
+ {
+ X509Certificate x509Certificate = (X509Certificate) cert;
+ String issuerName = x509Certificate.getIssuerX500Principal().getName();
+ if(certsToRemove.containsKey(issuerName) && certsToRemove.get(issuerName).contains(x509Certificate.getSerialNumber()))
+ {
+ iter.remove();
+ updated = true;
+ }
+ }
+ }
+
+
+ if(updated)
+ {
+ updateMap.put("storedCertificates", new ArrayList<>(certs));
+ }
+ return Futures.immediateFuture(null);
+ }
+
+ @Override
+ public String getObject()
+ {
+ return ManagedPeerCertificateTrustStoreImpl.this.toString();
+ }
+
+ @Override
+ public String getAction()
+ {
+ return "remove certificates";
+ }
+
+ @Override
+ public String getArguments()
+ {
+ return String.valueOf(certs);
+ }
+ }),
+ new Callable<ListenableFuture<Void>>()
+ {
+ @Override
+ public ListenableFuture<Void> call() throws Exception
+ {
+ if(updateMap.isEmpty())
+ {
+ return Futures.immediateFuture(null);
+ }
+ else
+ {
+ return setAttributesAsync(updateMap);
+ }
+ }
+
+ });
+ }
+
+ public static class CertificateDetailsImpl implements CertificateDetails, ManagedAttributeValue
+ {
+ private final X509Certificate _x509cert;
+
+ public CertificateDetailsImpl(final X509Certificate x509cert)
+ {
+ _x509cert = x509cert;
+ }
+
+ @Override
+ public String getSerialNumber()
+ {
+ return _x509cert.getSerialNumber().toString();
+ }
+
+ @Override
+ public int getVersion()
+ {
+ return _x509cert.getVersion();
+ }
+
+ @Override
+ public String getSignatureAlgorithm()
+ {
+ return _x509cert.getSigAlgName();
+ }
+
+ @Override
+ public String getIssuerName()
+ {
+ return _x509cert.getIssuerX500Principal().getName();
+ }
+
+ @Override
+ public String getSubjectName()
+ {
+ return _x509cert.getSubjectX500Principal().getName();
+ }
+
+ @Override
+ public List<String> getSubjectAltNames()
+ {
+ try
+ {
+ List<String> altNames = new ArrayList<String>();
+ final Collection<List<?>> altNameObjects = _x509cert.getSubjectAlternativeNames();
+ if(altNameObjects != null)
+ {
+ for (List<?> entry : altNameObjects)
+ {
+ final int type = (Integer) entry.get(0);
+ if (type == 1 || type == 2)
+ {
+ altNames.add(entry.get(1).toString().trim());
+ }
+
+ }
+ }
+ return altNames;
+ }
+ catch (CertificateParsingException e)
+ {
+
+ return Collections.emptyList();
+ }
+ }
+
+ @Override
+ public long getValidFrom()
+ {
+ return _x509cert.getNotBefore().getTime();
+ }
+
+ @Override
+ public long getValidUntil()
+ {
+ return _x509cert.getNotAfter().getTime();
+ }
+ }
}
Copied: qpid/java/trunk/broker-plugins/management-http/src/main/java/resources/js/qpid/management/store/managedcertificatestore/show.js (from r1715537, qpid/java/trunk/broker-plugins/management-http/src/main/java/resources/js/qpid/management/store/sitespecifictruststore/show.js)
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-plugins/management-http/src/main/java/resources/js/qpid/management/store/managedcertificatestore/show.js?p2=qpid/java/trunk/broker-plugins/management-http/src/main/java/resources/js/qpid/management/store/managedcertificatestore/show.js&p1=qpid/java/trunk/broker-plugins/management-http/src/main/java/resources/js/qpid/management/store/sitespecifictruststore/show.js&r1=1715537&r2=1716277&rev=1716277&view=diff
==============================================================================
--- qpid/java/trunk/broker-plugins/management-http/src/main/java/resources/js/qpid/management/store/sitespecifictruststore/show.js (original)
+++ qpid/java/trunk/broker-plugins/management-http/src/main/java/resources/js/qpid/management/store/managedcertificatestore/show.js Tue Nov 24 23:24:30 2015
@@ -18,32 +18,116 @@
*/
define(["dojo/query",
+ "dojo/_base/lang",
"qpid/common/util",
- "dojox/grid/DataGrid",
+ "dojox/grid/EnhancedGrid",
"qpid/common/UpdatableStore",
+ "dijit/registry",
"dojo/domReady!"],
- function (query, util, DataGrid, UpdatableStore)
+ function (query, lang, util, EnhancedGrid, UpdatableStore, registry)
{
+ function addIdToCertificates(obj) {
+ var certItems = [];
+ var certDetails = obj.certificateDetails;
+ for (var idx in certDetails)
+ {
+ var item = lang.mixin(certDetails[idx], {id: certDetails[idx].serialNumber + '|' + certDetails[idx].issuerName});
+ certItems.push(item);
+ }
+ return certItems;
+ }
- function SiteSpecificTrustStore(data)
+ function ManagedCertificateStore(data)
{
this.fields = [];
this.management = data.parent.management;
- var attributes = this.management.metadata.getMetaData("TrustStore", "SiteSpecificTrustStore").attributes;
+ this.modelObj = data.parent.modelObj;
+ var containerNode = data.containerNode;
+ var attributes = this.management.metadata.getMetaData("TrustStore", "ManagedCertificateStore").attributes;
for(var name in attributes)
{
this.fields.push(name);
}
var that = this;
- util.buildUI(data.containerNode, data.parent, "store/sitespecifictruststore/show.html", this.fields, this);
+ var gridProperties = {
+ height: 400,
+ selectionMode: "extended",
+ plugins: {
+ indirectSelection: true,
+ pagination: {
+ pageSizes: [10, 25, 50, 100],
+ description: true,
+ sizeSwitch: true,
+ pageStepper: true,
+ gotoButton: true,
+ maxPageStep: 4,
+ position: "bottom"
+ }
+ }};
+
+
+ util.buildUI(data.containerNode, data.parent, "store/managedcertificatestore/show.html", this.fields, this, function() {
+ that.certificates = addIdToCertificates(that);
+ that.certificatesGrid = new UpdatableStore(that.certificates, query(".managedCertificatesGrid", containerNode)[0],
+ [
+ { name: "Subject Name", field: "subjectName", width: "25%"},
+ { name: "Issuer Name", field: "issuerName", width: "25%"},
+ { name: "Serial #", field: "serialNumber", width: "10%"},
+ { name: "Valid From", field: "validFrom", width: "20%",
+ formatter: function(val)
+ {
+ return that.management.userPreferences.formatDateTime(val, {addOffset: true, appendTimeZone: true});
+ }
+ },
+ { name: "Valid Until", field: "validUntil", width: "20%",
+ formatter: function(val)
+ {
+ return that.management.userPreferences.formatDateTime(val, {addOffset: true, appendTimeZone: true});
+ }
+ }
+ ], function(obj) {
+ obj.grid.on("rowDblClick",
+ function(evt){
+ var idx = evt.rowIndex;
+ var theItem = this.getItem(idx);
+ that.download(theItem);
+ });
+ }, gridProperties, EnhancedGrid);
+ });
+
+ this.removeButton = registry.byNode(query(".removeCertificates", containerNode)[0]);
+ this.removeButton.on("click", function(e) {that.removeCertificates()} );
+
}
- SiteSpecificTrustStore.prototype.update = function(data)
+ ManagedCertificateStore.prototype.removeCertificates = function ()
+ {
+ var data = this.certificatesGrid.grid.selection.getSelected();
+
+ if(data.length)
+ {
+ var parentModelObj = this.modelObj;
+ var modelObj = {type: parentModelObj.type, name: "removeCertificates", parent: parentModelObj};
+ var items = [];
+ for(var i = 0; i < data.length; i++)
+ {
+ var parts = data[i].id.split("|");
+ items.push({ issuerName: parts[1], serialNumber: parts[0] });
+ }
+ var url = this.management.buildObjectURL(modelObj);
+ this.management.post({url: url}, {certificates: items});
+ }
+ };
+
+
+ ManagedCertificateStore.prototype.update = function(data)
{
util.updateUI(data, this.fields, this);
- }
+ this.certificates = addIdToCertificates(data);
+ this.certificatesGrid.update(this.certificates)
+ };
- return SiteSpecificTrustStore;
+ return ManagedCertificateStore;
}
);
Copied: qpid/java/trunk/broker-plugins/management-http/src/main/java/resources/store/managedcertificatestore/show.html (from r1715537, qpid/java/trunk/broker-plugins/management-http/src/main/java/resources/store/sitespecifictruststore/show.html)
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-plugins/management-http/src/main/java/resources/store/managedcertificatestore/show.html?p2=qpid/java/trunk/broker-plugins/management-http/src/main/java/resources/store/managedcertificatestore/show.html&p1=qpid/java/trunk/broker-plugins/management-http/src/main/java/resources/store/sitespecifictruststore/show.html&r1=1715537&r2=1716277&rev=1716277&view=diff
==============================================================================
--- qpid/java/trunk/broker-plugins/management-http/src/main/java/resources/store/sitespecifictruststore/show.html (original)
+++ qpid/java/trunk/broker-plugins/management-http/src/main/java/resources/store/managedcertificatestore/show.html Tue Nov 24 23:24:30 2015
@@ -18,36 +18,13 @@
-->
<div>
- <div class="clear">
- <div class="formLabel-labelCell">Site URL:</div>
- <div ><span class="siteUrl" ></span></div>
- </div>
- <div class="clear">
- <div class="formLabel-labelCell">Issuer:</div>
- <div><span class="certificateIssuer" ></span></div>
- </div>
- <div class="clear">
- <div class="formLabel-labelCell">Serial No.:</div>
- <div><span class="certificateSerialNumber" ></span></div>
- </div>
- <div class="clear">
- <div class="formLabel-labelCell">Subject:</div>
- <div><span class="certificateSubject" ></span></div>
- </div>
- <div class="clear">
- <div class="formLabel-labelCell">Valid From:</div>
- <div><span class="certificateValidFromDate" ></span></div>
- </div>
- <div class="clear">
- <div class="formLabel-labelCell">Valid Until:</div>
- <div><span class="certificateValidUntilDate" ></span></div>
- </div>
- <div class="clear">
- <div class="formLabel-labelCell">Signature:</div>
- <div><span class="certificateSignature" ></span></div>
+ <div class="clear"></div>
+ <div data-dojo-type="dijit.TitlePane" data-dojo-props="title: 'Certificates'" class="clear managedCertificatesGridPanel">
+ <div class="managedCertificatesGrid hidden"></div>
+ <div class="clear">
+ <button data-dojo-type="dijit.form.Button" class="removeCertificates">Remove Certificates</button>
+ </div>
</div>
-
-
<div class="clear"></div>
</div>
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org