blob: ed5e195043eaf36bc033d47e33b00b88b680845b [file] [log] [blame]
/*
*
* 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.jmx.mbeans;
import org.apache.qpid.management.common.mbeans.ManagedExchange;
import org.apache.qpid.server.jmx.AMQManagedObject;
import org.apache.qpid.server.jmx.ManagedObject;
import org.apache.qpid.server.model.Binding;
import org.apache.qpid.server.model.Exchange;
import org.apache.qpid.server.model.LifetimePolicy;
import org.apache.qpid.server.model.Queue;
import org.apache.qpid.server.model.VirtualHost;
import org.apache.qpid.server.util.ServerScopedRuntimeException;
import javax.management.JMException;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
import javax.management.OperationsException;
import javax.management.openmbean.ArrayType;
import javax.management.openmbean.CompositeData;
import javax.management.openmbean.CompositeDataSupport;
import javax.management.openmbean.CompositeType;
import javax.management.openmbean.OpenDataException;
import javax.management.openmbean.OpenType;
import javax.management.openmbean.SimpleType;
import javax.management.openmbean.TabularData;
import javax.management.openmbean.TabularDataSupport;
import javax.management.openmbean.TabularType;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class ExchangeMBean extends AMQManagedObject implements ManagedExchange
{
public static final String FANOUT_EXCHANGE_TYPE = "fanout";
public static final String HEADERS_EXCHANGE_TYPE = "headers";
private static final String[] TABULAR_UNIQUE_INDEX_ARRAY =
TABULAR_UNIQUE_INDEX.toArray(new String[TABULAR_UNIQUE_INDEX.size()]);
private static final String[] COMPOSITE_ITEM_NAMES_ARRAY =
COMPOSITE_ITEM_NAMES.toArray(new String[COMPOSITE_ITEM_NAMES.size()]);
private static final String[] COMPOSITE_ITEM_DESCRIPTIONS_ARRAY =
COMPOSITE_ITEM_DESCRIPTIONS.toArray(new String[COMPOSITE_ITEM_DESCRIPTIONS.size()]);
private static final OpenType[] BINDING_ITEM_TYPES;
private static final CompositeType BINDING_DATA_TYPE;
private static final OpenType[] HEADERS_BINDING_ITEM_TYPES;
private static final CompositeType HEADERS_BINDING_DATA_TYPE;
private static final String[] HEADERS_COMPOSITE_ITEM_NAMES_ARRAY =
HEADERS_COMPOSITE_ITEM_NAMES.toArray(new String[HEADERS_COMPOSITE_ITEM_NAMES.size()]);
private static final String[] HEADERS_COMPOSITE_ITEM_DESCS_ARRAY =
HEADERS_COMPOSITE_ITEM_DESC.toArray(new String[HEADERS_COMPOSITE_ITEM_DESC.size()]);
private static final String[] HEADERS_TABULAR_UNIQUE_INDEX_ARRAY =
HEADERS_TABULAR_UNIQUE_INDEX.toArray(new String[HEADERS_TABULAR_UNIQUE_INDEX.size()]);
static
{
try
{
BINDING_ITEM_TYPES = new OpenType[] {SimpleType.STRING, new ArrayType(1, SimpleType.STRING)};
BINDING_DATA_TYPE= new CompositeType("Exchange Binding", "Binding key and Queue names",
COMPOSITE_ITEM_NAMES_ARRAY,
COMPOSITE_ITEM_DESCRIPTIONS_ARRAY,
BINDING_ITEM_TYPES);
HEADERS_BINDING_ITEM_TYPES = new OpenType[] {SimpleType.INTEGER,
SimpleType.STRING,
new ArrayType(1, SimpleType.STRING)};
HEADERS_BINDING_DATA_TYPE = new CompositeType("Exchange Binding", "Queue name and header bindings",
HEADERS_COMPOSITE_ITEM_NAMES_ARRAY,
HEADERS_COMPOSITE_ITEM_DESCS_ARRAY,
HEADERS_BINDING_ITEM_TYPES);
}
catch(OpenDataException e)
{
throw new ServerScopedRuntimeException("Unexpected Error creating ArrayType", e);
}
}
private final Exchange _exchange;
private final VirtualHostMBean _vhostMBean;
protected ExchangeMBean(Exchange exchange, VirtualHostMBean virtualHostMBean)
throws JMException
{
super(ManagedExchange.class, ManagedExchange.TYPE, virtualHostMBean.getRegistry());
_exchange = exchange;
_vhostMBean = virtualHostMBean;
register();
}
public String getObjectInstanceName()
{
return ObjectName.quote(getName());
}
@Override
public ManagedObject getParentObject()
{
return _vhostMBean;
}
public ObjectName getObjectName() throws MalformedObjectNameException
{
String objNameString = super.getObjectName().toString();
objNameString = objNameString + ",ExchangeType=" + getExchangeType();
return new ObjectName(objNameString);
}
public String getName()
{
return _exchange.getName();
}
public String getExchangeType()
{
return _exchange.getExchangeType();
}
public Integer getTicketNo()
{
return 0;
}
public boolean isDurable()
{
return _exchange.isDurable();
}
public boolean isAutoDelete()
{
return _exchange.getLifetimePolicy() != LifetimePolicy.PERMANENT;
}
public TabularData bindings() throws IOException, JMException
{
if(HEADERS_EXCHANGE_TYPE.equals(_exchange.getExchangeType()))
{
return getHeadersBindings(_exchange.getBindings());
}
else
{
return getNonHeadersBindings(_exchange.getBindings());
}
}
private TabularData getHeadersBindings(Collection<Binding> bindings) throws OpenDataException
{
TabularType bindinglistDataType =
new TabularType("Exchange Bindings", "List of exchange bindings for " + getName(),
HEADERS_BINDING_DATA_TYPE,
HEADERS_TABULAR_UNIQUE_INDEX_ARRAY);
TabularDataSupport bindingList = new TabularDataSupport(bindinglistDataType);
int count = 1;
for (Binding binding : bindings)
{
String queueName = binding.getParent(Queue.class).getName();
Map<String,Object> headerMappings = binding.getArguments();
final List<String> mappingList = new ArrayList<String>();
if(headerMappings != null)
{
for(Map.Entry<String,Object> entry : headerMappings.entrySet())
{
mappingList.add(entry.getKey() + "=" + entry.getValue());
}
}
Object[] bindingItemValues = {count++, queueName, mappingList.toArray(new String[0])};
CompositeData bindingData = new CompositeDataSupport(HEADERS_BINDING_DATA_TYPE,
HEADERS_COMPOSITE_ITEM_NAMES_ARRAY,
bindingItemValues);
bindingList.put(bindingData);
}
return bindingList;
}
private TabularData getNonHeadersBindings(Collection<Binding> bindings) throws OpenDataException
{
TabularType bindinglistDataType =
new TabularType("Exchange Bindings", "Exchange Bindings for " + getName(),
BINDING_DATA_TYPE,
TABULAR_UNIQUE_INDEX_ARRAY);
TabularDataSupport bindingList = new TabularDataSupport(bindinglistDataType);
Map<String, List<String>> bindingMap = new HashMap<String, List<String>>();
for (Binding binding : bindings)
{
String key = FANOUT_EXCHANGE_TYPE.equals(_exchange.getExchangeType()) ? "*" : binding.getName();
List<String> queueList = bindingMap.get(key);
if(queueList == null)
{
queueList = new ArrayList<String>();
bindingMap.put(key, queueList);
}
queueList.add(binding.getParent(Queue.class).getName());
}
for(Map.Entry<String, List<String>> entry : bindingMap.entrySet())
{
Object[] bindingItemValues = {entry.getKey(), entry.getValue().toArray(new String[0])};
CompositeData bindingData = new CompositeDataSupport(BINDING_DATA_TYPE,
COMPOSITE_ITEM_NAMES_ARRAY,
bindingItemValues);
bindingList.put(bindingData);
}
return bindingList;
}
public void createNewBinding(String queueName, String binding) throws JMException
{
final Map<String,Object> arguments = new HashMap<String, Object>();
createNewBinding(queueName, binding, arguments);
}
@Override
public void createNewBinding(String queueName, String binding, Map<String, Object> arguments) throws JMException
{
if(HEADERS_EXCHANGE_TYPE.equals(_exchange.getExchangeType()))
{
arguments = new HashMap<String, Object>(arguments);
final String[] bindings = binding.split(",");
for (int i = 0; i < bindings.length; i++)
{
final String[] keyAndValue = bindings[i].split("=");
if (keyAndValue == null || keyAndValue.length == 0 || keyAndValue.length > 2 || keyAndValue[0].length() == 0)
{
throw new JMException("Format for headers binding should be \"<attribute1>=<value1>,<attribute2>=<value2>\"");
}
if(keyAndValue.length == 1)
{
//no value was given, only a key. Use an empty value to signal match on key presence alone
arguments.put(keyAndValue[0], "");
}
else
{
arguments.put(keyAndValue[0], keyAndValue[1]);
}
}
}
VirtualHost virtualHost = _exchange.getParent(VirtualHost.class);
Queue queue = MBeanUtils.findQueueFromQueueName(virtualHost, queueName);
_exchange.createBinding(binding, queue, arguments, Collections.EMPTY_MAP);
}
public void removeBinding(String queueName, String bindingKey)
throws IOException, JMException
{
VirtualHost virtualHost = _exchange.getParent(VirtualHost.class);
Queue queue = MBeanUtils.findQueueFromQueueName(virtualHost, queueName);;
boolean deleted = false;
for(Binding binding : _exchange.getBindings())
{
if(queue.equals(binding.getParent(Queue.class)) && bindingKey.equals(binding.getName()))
{
binding.delete();
deleted = true;
}
}
if (!deleted)
{
throw new OperationsException("No such binding \"" + bindingKey + "\" on queue \"" + queueName + "\"");
}
}
}