diff options
Diffstat (limited to 'java/broker/src/main/java')
144 files changed, 12429 insertions, 1887 deletions
diff --git a/java/broker/src/main/java/org/apache/qpid/qmf/CompletionCode.java b/java/broker/src/main/java/org/apache/qpid/qmf/CompletionCode.java new file mode 100644 index 0000000000..706ab3974a --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/qmf/CompletionCode.java @@ -0,0 +1,36 @@ +/* + * + * 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.qmf; + +public enum CompletionCode +{ + OK, + UNKNOWN_OBJECT, + UNKNOWN_METHOD, + NOT_IMPLEMENTED, + INVALID_PARAMETER, + FEATURE_NOT_IMPLEMENTED, + FORBIDDEN, + EXCEPTION, + UNKNOWN_PACKAGE, + UNKNOWN_CLASS; +} diff --git a/java/broker/src/main/java/org/apache/qpid/qmf/ManagementExchange.java b/java/broker/src/main/java/org/apache/qpid/qmf/ManagementExchange.java new file mode 100644 index 0000000000..b639cb9fc1 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/qmf/ManagementExchange.java @@ -0,0 +1,559 @@ +/* + * + * 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.qmf; + +import org.apache.qpid.AMQException; +import org.apache.qpid.framing.AMQShortString; +import org.apache.qpid.framing.FieldTable; +import org.apache.qpid.server.binding.Binding; +import org.apache.qpid.server.configuration.ConfigStore; +import org.apache.qpid.server.configuration.ConfiguredObject; +import org.apache.qpid.server.configuration.ExchangeConfigType; +import org.apache.qpid.server.exchange.Exchange; +import org.apache.qpid.server.exchange.ExchangeReferrer; +import org.apache.qpid.server.exchange.ExchangeType; +import org.apache.qpid.server.exchange.topic.TopicBinding; +import org.apache.qpid.server.exchange.topic.TopicExchangeResult; +import org.apache.qpid.server.exchange.topic.TopicMatcherResult; +import org.apache.qpid.server.exchange.topic.TopicNormalizer; +import org.apache.qpid.server.exchange.topic.TopicParser; +import org.apache.qpid.server.message.AMQMessageHeader; +import org.apache.qpid.server.message.InboundMessage; +import org.apache.qpid.server.message.ServerMessage; +import org.apache.qpid.server.queue.AMQQueue; +import org.apache.qpid.server.queue.BaseQueue; +import org.apache.qpid.server.virtualhost.VirtualHost; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.TimerTask; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.atomic.AtomicLong; + +public class ManagementExchange implements Exchange, QMFService.Listener +{ + private static final AMQShortString QPID_MANAGEMENT = new AMQShortString("qpid.management"); + private static final AMQShortString QPID_MANAGEMENT_TYPE = new AMQShortString("management"); + + private VirtualHost _virtualHost; + + private final TopicParser _parser = new TopicParser(); + + private final Map<AMQShortString, TopicExchangeResult> _topicExchangeResults = + new ConcurrentHashMap<AMQShortString, TopicExchangeResult>(); + + private final Map<TopicBinding, FieldTable> _topicBindings = new HashMap<TopicBinding, FieldTable>(); + private final Set<Binding> _bindingSet = new HashSet<Binding>(); + private UUID _id; + private static final String AGENT_BANK = "0"; + + private int _bindingCountHigh; + private final AtomicLong _msgReceived = new AtomicLong(); + private final AtomicLong _bytesReceived = new AtomicLong(); + + private final CopyOnWriteArrayList<BindingListener> _listeners = new CopyOnWriteArrayList<Exchange.BindingListener>(); + + // TODO + private long _createTime = System.currentTimeMillis(); + + + private class ManagementQueue implements BaseQueue + { + private final String NAME_AS_STRING = "##__mgmt_pseudo_queue__##" + UUID.randomUUID().toString(); + private final AMQShortString NAME_AS_SHORT_STRING = new AMQShortString(NAME_AS_STRING); + + public void enqueue(ServerMessage message) throws AMQException + { + AMQMessageHeader h = message.getMessageHeader(); + long size = message.getSize(); + + ByteBuffer buf = ByteBuffer.allocate((int) size); + + int offset = 0; + + while(offset < size) + { + offset += message.getContent(buf,offset); + } + + buf.flip(); + QMFCommandDecoder commandDecoder = new QMFCommandDecoder(getQMFService(),buf); + QMFCommand cmd; + while((cmd = commandDecoder.decode()) != null) + { + cmd.process(_virtualHost, message); + } + + } + + public void enqueue(ServerMessage message, PostEnqueueAction action) throws AMQException + { + enqueue(message); + } + + public boolean isDurable() + { + return false; + } + + public AMQShortString getNameShortString() + { + return NAME_AS_SHORT_STRING; + } + + public String getResourceName() + { + return NAME_AS_STRING; + } + } + + + private final ManagementQueue _mgmtQueue = new ManagementQueue(); + + public ManagementExchange() + { + } + + public static final ExchangeType<ManagementExchange> TYPE = new ExchangeType<ManagementExchange>() + { + + public AMQShortString getName() + { + return QPID_MANAGEMENT_TYPE; + } + + public Class<ManagementExchange> getExchangeClass() + { + return ManagementExchange.class; + } + + public ManagementExchange newInstance(VirtualHost host, + AMQShortString name, + boolean durable, + int ticket, + boolean autoDelete) throws AMQException + { + ManagementExchange exch = new ManagementExchange(); + exch.initialise(host, name, durable, ticket, autoDelete); + return exch; + } + + public AMQShortString getDefaultExchangeName() + { + return QPID_MANAGEMENT; + } + }; + + + public AMQShortString getNameShortString() + { + return QPID_MANAGEMENT; + } + + public AMQShortString getTypeShortString() + { + return QPID_MANAGEMENT_TYPE; + } + + public void initialise(VirtualHost host, AMQShortString name, boolean durable, int ticket, boolean autoDelete) + throws AMQException + { + if(!QPID_MANAGEMENT.equals(name)) + { + throw new AMQException("Can't create more than one Management exchange"); + } + _virtualHost = host; + _id = host.getConfigStore().createId(); + _virtualHost.scheduleTask(_virtualHost.getBroker().getManagementPublishInterval(),_updateTask); + getConfigStore().addConfiguredObject(this); + getQMFService().addListener(this); + } + + public UUID getId() + { + return _id; + } + + public ExchangeConfigType getConfigType() + { + return ExchangeConfigType.getInstance(); + } + + public ConfiguredObject getParent() + { + return _virtualHost; + } + + public boolean isDurable() + { + return true; + } + + public VirtualHost getVirtualHost() + { + return _virtualHost; + } + + public String getName() + { + return QPID_MANAGEMENT.toString(); + } + + public ExchangeType getType() + { + return TYPE; + } + + public boolean isAutoDelete() + { + return false; + } + + public int getTicket() + { + return 0; + } + + public void close() throws AMQException + { + getConfigStore().removeConfiguredObject(this); + } + + public ConfigStore getConfigStore() + { + return getVirtualHost().getConfigStore(); + } + + public synchronized void addBinding(final Binding b) + { + + _bindingSet.add(b); + + for(BindingListener listener : _listeners) + { + listener.bindingAdded(this, b); + } + + if(_bindingSet.size() > _bindingCountHigh) + { + _bindingCountHigh = _bindingSet.size(); + } + + TopicBinding binding = new TopicBinding(new AMQShortString(b.getBindingKey()), b.getQueue(), null); + + if(!_topicBindings.containsKey(binding)) + { + AMQShortString routingKey = TopicNormalizer.normalize(new AMQShortString(b.getBindingKey())); + + TopicExchangeResult result = _topicExchangeResults.get(routingKey); + if(result == null) + { + result = new TopicExchangeResult(); + result.addUnfilteredQueue(b.getQueue()); + _parser.addBinding(routingKey, result); + _topicExchangeResults.put(routingKey,result); + } + else + { + result.addUnfilteredQueue(b.getQueue()); + } + _topicBindings.put(binding, null); + + + } + String bindingKey = b.getBindingKey(); + + if(bindingKey.startsWith("schema.") || bindingKey.startsWith("*.") || bindingKey.startsWith("#.")) + { + publishAllSchema(); + } + if(bindingKey.startsWith("console.") || bindingKey.startsWith("*.") || bindingKey.startsWith("#.")) + { + publishAllConsole(); + } + + } + + void publishAllConsole() + { + QMFService qmfService = getQMFService(); + + long sampleTime = System.currentTimeMillis(); + + for(QMFPackage pkg : qmfService.getSupportedSchemas()) + { + for(QMFClass qmfClass : pkg.getClasses()) + { + Collection<QMFObject> qmfObjects = qmfService.getObjects(qmfClass); + + publishObjectsToConsole(sampleTime, qmfObjects); + } + + } + + } + + private QMFService getQMFService() + { + return _virtualHost.getApplicationRegistry().getQMFService(); + } + + void publishObjectsToConsole(final long sampleTime, + final Collection<QMFObject> qmfObjects) + { + if(!qmfObjects.isEmpty() && hasBindings()) + { + QMFClass qmfClass = qmfObjects.iterator().next().getQMFClass(); + ArrayList<QMFCommand> commands = new ArrayList<QMFCommand>(); + + + for(QMFObject obj : qmfObjects) + { + commands.add(obj.asConfigInfoCmd(sampleTime)); + commands.add(obj.asInstrumentInfoCmd(sampleTime)); + } + + publishToConsole(qmfClass, commands); + } + } + + private void publishToConsole(final QMFClass qmfClass, final ArrayList<QMFCommand> commands) + { + if(!commands.isEmpty() && hasBindings()) + { + String routingKey = "console.obj.1." + AGENT_BANK + "." + qmfClass.getPackage().getName() + "." + qmfClass.getName(); + QMFMessage message = new QMFMessage(routingKey,commands.toArray(new QMFCommand[commands.size()])); + + Collection<TopicMatcherResult> results = _parser.parse(new AMQShortString(routingKey)); + HashSet<AMQQueue> queues = new HashSet<AMQQueue>(); + for(TopicMatcherResult result : results) + { + queues.addAll(((TopicExchangeResult)result).getUnfilteredQueues()); + } + for(AMQQueue queue : queues) + { + try + { + queue.enqueue(message); + } + catch (AMQException e) + { + throw new RuntimeException(e); + } + } + } + } + + void publishAllSchema() + { + + } + + public synchronized void removeBinding(final Binding binding) + { + _bindingSet.remove(binding); + + TopicBinding topicBinding = new TopicBinding(new AMQShortString(binding.getBindingKey()), binding.getQueue(), null); + + if(_topicBindings.containsKey(topicBinding)) + { + AMQShortString bindingKey = TopicNormalizer.normalize(topicBinding.getBindingKey()); + TopicExchangeResult result = _topicExchangeResults.get(bindingKey); + result.removeUnfilteredQueue(binding.getQueue()); + } + + for(BindingListener listener : _listeners) + { + listener.bindingRemoved(this, binding); + } + } + + public synchronized Collection<Binding> getBindings() + { + return new ArrayList<Binding>(_bindingSet); + } + + public ArrayList<BaseQueue> route(InboundMessage message) + { + ArrayList<BaseQueue> queues = new ArrayList<BaseQueue>(1); + _msgReceived.incrementAndGet(); + _bytesReceived.addAndGet(message.getSize()); + queues.add(_mgmtQueue); + return queues; + } + + public boolean isBound(AMQShortString routingKey, FieldTable arguments, AMQQueue queue) + { + return false; //To change body of implemented methods use File | Settings | File Templates. + } + + public boolean isBound(AMQShortString routingKey, AMQQueue queue) + { + return false; //To change body of implemented methods use File | Settings | File Templates. + } + + public boolean isBound(AMQShortString routingKey) + { + return false; //To change body of implemented methods use File | Settings | File Templates. + } + + public boolean isBound(AMQQueue queue) + { + return false; //To change body of implemented methods use File | Settings | File Templates. + } + + public boolean hasBindings() + { + return !_bindingSet.isEmpty(); + } + + public boolean isBound(String bindingKey, AMQQueue queue) + { + return false; //To change body of implemented methods use File | Settings | File Templates. + } + + public boolean isBound(String bindingKey) + { + return false; //To change body of implemented methods use File | Settings | File Templates. + } + + public void addCloseTask(final Task task) + { + //To change body of implemented methods use File | Settings | File Templates. + } + + public void removeCloseTask(final Task task) + { + //To change body of implemented methods use File | Settings | File Templates. + } + + + + public Exchange getAlternateExchange() + { + return null; + } + + public Map<String, Object> getArguments() + { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + + public void setAlternateExchange(Exchange exchange) + { + + } + + public void removeReference(ExchangeReferrer exchange) + { + } + + public void addReference(ExchangeReferrer exchange) + { + } + + public boolean hasReferrers() + { + return true; + } + + + + private final TimerTask _updateTask = new UpdateTask(); + + + private class UpdateTask extends TimerTask + { + + public void run() + { + publishAllConsole(); + publishAllSchema(); + + } + + } + + public void objectCreated(final QMFObject obj) + { + publishObjectsToConsole(System.currentTimeMillis(), Collections.singleton(obj)); + } + + public void objectDeleted(final QMFObject obj) + { + publishObjectsToConsole(System.currentTimeMillis(), Collections.singleton(obj)); + } + + public long getBindingCount() + { + return getBindings().size(); + } + + public long getBindingCountHigh() + { + return _bindingCountHigh; + } + + public long getMsgReceives() + { + return _msgReceived.get(); + } + + public long getMsgRoutes() + { + return getMsgReceives(); + } + + public long getByteReceives() + { + return _bytesReceived.get(); + } + + public long getByteRoutes() + { + return getByteReceives(); + } + + public long getCreateTime() + { + return _createTime; + } + + public void addBindingListener(final BindingListener listener) + { + _listeners.add(listener); + } + + public void removeBindingListener(final BindingListener listener) + { + _listeners.remove(listener); + } + +} diff --git a/java/broker/src/main/java/org/apache/qpid/qmf/QMFBrokerRequestCommand.java b/java/broker/src/main/java/org/apache/qpid/qmf/QMFBrokerRequestCommand.java new file mode 100644 index 0000000000..b98daf7cb1 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/qmf/QMFBrokerRequestCommand.java @@ -0,0 +1,78 @@ +/* + * + * 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.qmf; + +import org.apache.qpid.transport.codec.BBDecoder; +import org.apache.qpid.transport.codec.BBEncoder; +import org.apache.qpid.server.message.ServerMessage; +import org.apache.qpid.server.message.MessageTransferMessage; +import org.apache.qpid.server.virtualhost.VirtualHost; +import org.apache.qpid.server.exchange.Exchange; +import org.apache.qpid.server.queue.BaseQueue; +import org.apache.qpid.AMQException; +import org.apache.qpid.management.common.mbeans.ManagedConnection; + +import java.util.ArrayList; + +public class QMFBrokerRequestCommand extends QMFCommand +{ + + public QMFBrokerRequestCommand(QMFCommandHeader header, BBDecoder buf) + { + super(header); + } + + public void process(VirtualHost virtualHost, ServerMessage message) + { + String exchangeName = message.getMessageHeader().getReplyToExchange(); + String queueName = message.getMessageHeader().getReplyToRoutingKey(); + + QMFCommand[] commands = new QMFCommand[2]; + commands[0] = new QMFBrokerResponseCommand(this, virtualHost); + commands[1] = new QMFCommandCompletionCommand(this); + + Exchange exchange = virtualHost.getExchangeRegistry().getExchange(exchangeName); + + for(QMFCommand cmd : commands) + { + QMFMessage responseMessage = new QMFMessage(queueName, cmd); + + + ArrayList<? extends BaseQueue> queues = exchange.route(responseMessage); + + + for(BaseQueue q : queues) + { + try + { + q.enqueue(responseMessage); + } + catch (AMQException e) + { + e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. + } + } + } + } + + +} diff --git a/java/broker/src/main/java/org/apache/qpid/qmf/QMFBrokerResponseCommand.java b/java/broker/src/main/java/org/apache/qpid/qmf/QMFBrokerResponseCommand.java new file mode 100644 index 0000000000..ac01c47fe8 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/qmf/QMFBrokerResponseCommand.java @@ -0,0 +1,46 @@ +/* + * + * 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.qmf; + +import org.apache.qpid.server.virtualhost.VirtualHost; +import org.apache.qpid.server.message.ServerMessage; +import org.apache.qpid.transport.codec.BBEncoder; + +public class QMFBrokerResponseCommand extends QMFCommand +{ + private QMFCommandHeader _header; + private VirtualHost _virtualHost; + + public QMFBrokerResponseCommand(QMFBrokerRequestCommand qmfBrokerRequestCommand, VirtualHost virtualHost) + { + super( new QMFCommandHeader(qmfBrokerRequestCommand.getHeader().getVersion(), + qmfBrokerRequestCommand.getHeader().getSeq(), + QMFOperation.BROKER_RESPONSE)); + _virtualHost = virtualHost; + } + + public void encode(BBEncoder encoder) + { + super.encode(encoder); + encoder.writeUuid(_virtualHost.getBrokerId()); + } +} diff --git a/java/broker/src/main/java/org/apache/qpid/qmf/QMFClass.java b/java/broker/src/main/java/org/apache/qpid/qmf/QMFClass.java new file mode 100644 index 0000000000..3408ff09f4 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/qmf/QMFClass.java @@ -0,0 +1,158 @@ +/* + * + * 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.qmf; + +import org.apache.qpid.server.configuration.ConfiguredObject; + +import java.util.Collection; +import java.util.Map; +import java.util.List; +import java.util.LinkedHashMap; + +abstract public class QMFClass +{ + + + public enum Type + { + OBJECT((byte)1), + EVENT((byte)2); + + private final byte _value; + + Type(byte value) + { + _value = value; + } + + public byte getValue() + { + return _value; + } + } + + private final Type _type; + private QMFPackage _package; + private final String _name; + private byte[] _schemaHash; + + private Map<String, QMFProperty> _properties = new LinkedHashMap<String, QMFProperty>(); + private Map<String, QMFStatistic> _statistics = new LinkedHashMap<String, QMFStatistic>(); + private Map<String, QMFMethod> _methods = new LinkedHashMap<String, QMFMethod>(); + + + + public QMFClass(Type type, String name, byte[] schemaHash, List<QMFProperty> properties, + List<QMFStatistic> statistics, List<QMFMethod> methods) + { + this(type, name, schemaHash); + setProperties(properties); + setStatistics(statistics); + setMethods(methods); + } + + + public QMFClass(Type type, String name, byte[] schemaHash) + + { + _type = type; + _name = name; + _schemaHash = schemaHash; + + } + + protected void setProperties(List<QMFProperty> properties) + { + for(QMFProperty prop : properties) + { + _properties.put(prop.getName(), prop); + } + } + + protected void setStatistics(List<QMFStatistic> statistics) + { + for(QMFStatistic stat : statistics) + { + _statistics.put(stat.getName(), stat); + } + } + + + protected void setMethods(List<QMFMethod> methods) + { + for(QMFMethod method : methods) + { + _methods.put(method.getName(), method); + } + } + + public void setPackage(QMFPackage aPackage) + { + _package = aPackage; + for(QMFProperty prop : _properties.values()) + { + prop.setQMFClass(this); + } + // TODO Statisics, Methods + } + + public Type getType() + { + return _type; + } + + public QMFPackage getPackage() + { + return _package; + } + + public String getName() + { + return _name; + } + + public byte[] getSchemaHash() + { + return _schemaHash; + } + + public Collection<QMFProperty> getProperties() + { + return _properties.values(); + } + + public Collection<QMFStatistic> getStatistics() + { + return _statistics.values(); + } + + public Collection<QMFMethod> getMethods() + { + return _methods.values(); + } + + public QMFMethod getMethod(String methodName) + { + return _methods.get(methodName); + } + +} diff --git a/java/broker/src/main/java/org/apache/qpid/qmf/QMFClassIndicationCommand.java b/java/broker/src/main/java/org/apache/qpid/qmf/QMFClassIndicationCommand.java new file mode 100644 index 0000000000..a956a9bd70 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/qmf/QMFClassIndicationCommand.java @@ -0,0 +1,50 @@ +/* + * + * 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.qmf; + +import org.apache.qpid.server.virtualhost.VirtualHost; +import org.apache.qpid.server.message.ServerMessage; +import org.apache.qpid.transport.codec.BBEncoder; + +public class QMFClassIndicationCommand extends QMFCommand +{ + private QMFClass _qmfClass; + + public QMFClassIndicationCommand(QMFClassQueryCommand qmfClassQueryCommand, QMFClass qmfClass) + { + super(new QMFCommandHeader(qmfClassQueryCommand.getHeader().getVersion(), + qmfClassQueryCommand.getHeader().getSeq(), + QMFOperation.CLASS_INDICATION)); + _qmfClass = qmfClass; + } + + + @Override + public void encode(BBEncoder encoder) + { + super.encode(encoder); + encoder.writeUint8(_qmfClass.getType().getValue()); + encoder.writeStr8(_qmfClass.getPackage().getName()); + encoder.writeStr8(_qmfClass.getName()); + encoder.writeBin128(_qmfClass.getSchemaHash()); + } +} diff --git a/java/broker/src/main/java/org/apache/qpid/qmf/QMFClassQueryCommand.java b/java/broker/src/main/java/org/apache/qpid/qmf/QMFClassQueryCommand.java new file mode 100644 index 0000000000..26a27cfa19 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/qmf/QMFClassQueryCommand.java @@ -0,0 +1,90 @@ +/* + * + * 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.qmf; + +import org.apache.qpid.transport.codec.BBDecoder; +import org.apache.qpid.server.virtualhost.VirtualHost; +import org.apache.qpid.server.message.ServerMessage; +import org.apache.qpid.server.exchange.Exchange; +import org.apache.qpid.server.queue.BaseQueue; +import org.apache.qpid.server.registry.IApplicationRegistry; +import org.apache.qpid.AMQException; + +import java.util.ArrayList; +import java.util.Collection; + +public class QMFClassQueryCommand extends QMFCommand +{ + private final String _package; + + public QMFClassQueryCommand(QMFCommandHeader header, BBDecoder decoder) + { + super(header); + _package = decoder.readStr8(); + } + + public void process(VirtualHost virtualHost, ServerMessage message) + { + String exchangeName = message.getMessageHeader().getReplyToExchange(); + String routingKey = message.getMessageHeader().getReplyToRoutingKey(); + + IApplicationRegistry appRegistry = virtualHost.getApplicationRegistry(); + QMFService service = appRegistry.getQMFService(); + + QMFPackage qmfPackage = service.getPackage(_package); + Collection<QMFClass> qmfClasses = qmfPackage.getClasses(); + + QMFCommand[] commands = new QMFCommand[ qmfClasses.size() + 1 ]; + + int i = 0; + for(QMFClass qmfClass : qmfClasses) + { + commands[i++] = new QMFClassIndicationCommand(this, qmfClass); + } + commands[ commands.length - 1 ] = new QMFCommandCompletionCommand(this); + + + for(QMFCommand cmd : commands) + { + + + QMFMessage responseMessage = new QMFMessage(routingKey, cmd); + + Exchange exchange = virtualHost.getExchangeRegistry().getExchange(exchangeName); + + ArrayList<? extends BaseQueue> queues = exchange.route(responseMessage); + + for(BaseQueue q : queues) + { + try + { + q.enqueue(responseMessage); + } + catch (AMQException e) + { + e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. + } + } + } + } + +} diff --git a/java/broker/src/main/java/org/apache/qpid/qmf/QMFCommand.java b/java/broker/src/main/java/org/apache/qpid/qmf/QMFCommand.java new file mode 100644 index 0000000000..4f143701af --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/qmf/QMFCommand.java @@ -0,0 +1,54 @@ +/* + * + * 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.qmf; + +import org.apache.qpid.server.message.ServerMessage; +import org.apache.qpid.server.virtualhost.VirtualHost; +import org.apache.qpid.transport.codec.BBEncoder; + +public abstract class QMFCommand +{ + + private final QMFCommandHeader _header; + + protected QMFCommand(QMFCommandHeader header) + { + _header = header; + } + + + public void process(final VirtualHost virtualHost, final ServerMessage message) + { + throw new UnsupportedOperationException(); + } + + public void encode(BBEncoder encoder) + { + _header.encode(encoder); + + } + + public QMFCommandHeader getHeader() + { + return _header; + } +} diff --git a/java/broker/src/main/java/org/apache/qpid/qmf/QMFCommandCompletionCommand.java b/java/broker/src/main/java/org/apache/qpid/qmf/QMFCommandCompletionCommand.java new file mode 100644 index 0000000000..f163e434d1 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/qmf/QMFCommandCompletionCommand.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.qmf; + +import org.apache.qpid.server.virtualhost.VirtualHost; +import org.apache.qpid.server.message.ServerMessage; +import org.apache.qpid.transport.codec.BBEncoder; + +public class QMFCommandCompletionCommand extends QMFCommand +{ + + private final CompletionCode _status; + private final String _text; + + public QMFCommandCompletionCommand(QMFCommand command) + { + this(command, CompletionCode.OK, ""); + } + public QMFCommandCompletionCommand(QMFCommand command, CompletionCode status, String text) + { + super( new QMFCommandHeader(command.getHeader().getVersion(), + command.getHeader().getSeq(), + QMFOperation.COMMAND_COMPLETION)); + + _status = status; + _text = text; + } + + + @Override + public void encode(BBEncoder encoder) + { + super.encode(encoder); + encoder.writeInt32(_status.ordinal()); + encoder.writeStr8(_text); + } +} diff --git a/java/broker/src/main/java/org/apache/qpid/qmf/QMFCommandDecoder.java b/java/broker/src/main/java/org/apache/qpid/qmf/QMFCommandDecoder.java new file mode 100644 index 0000000000..ac036dfa19 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/qmf/QMFCommandDecoder.java @@ -0,0 +1,98 @@ +/* + * + * 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.qmf; + +import org.apache.qpid.transport.codec.BBDecoder; + +import java.nio.ByteBuffer; + +public class QMFCommandDecoder +{ + private BBDecoder _decoder; + + + private static final QMFOperation[] OP_CODES = new QMFOperation[256]; + private final QMFService _qmfService; + + static + { + for(QMFOperation op : QMFOperation.values()) + { + OP_CODES[op.getOpcode()] = op; + } + } + + public QMFCommandDecoder(final QMFService qmfService, ByteBuffer buf) + { + _qmfService = qmfService; + _decoder = new BBDecoder(); + _decoder.init(buf); + } + + public QMFCommand decode() + { + if(_decoder.hasRemaining()) + { + QMFCommandHeader header = readQMFHeader(); + + switch(header.getOperation()) + { + case BROKER_REQUEST: + return new QMFBrokerRequestCommand(header, _decoder); + case PACKAGE_QUERY: + return new QMFPackageQueryCommand(header, _decoder); + case CLASS_QUERY: + return new QMFClassQueryCommand(header, _decoder); + case SCHEMA_REQUEST: + return new QMFSchemaRequestCommand(header, _decoder); + case METHOD_REQUEST: + return new QMFMethodRequestCommand(header, _decoder, _qmfService); + case GET_QUERY: + return new QMFGetQueryCommand(header, _decoder); + default: + System.out.println("Unknown command"); + + } + + return null; + } + else + { + return null; + } + } + + private QMFCommandHeader readQMFHeader() + { + if(_decoder.readInt8() == (byte) 'A' + && _decoder.readInt8() == (byte) 'M') + { + byte version = _decoder.readInt8(); + short opCode = _decoder.readUint8(); + int seq = _decoder.readInt32(); + + return new QMFCommandHeader(version, seq, OP_CODES[opCode]); + + } + return null; + } +} diff --git a/java/broker/src/main/java/org/apache/qpid/qmf/QMFCommandHeader.java b/java/broker/src/main/java/org/apache/qpid/qmf/QMFCommandHeader.java new file mode 100644 index 0000000000..c4d771317f --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/qmf/QMFCommandHeader.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.qmf; + +import org.apache.qpid.transport.codec.BBEncoder; + +public class QMFCommandHeader +{ + private final byte _version; + private final int _seq; + + private final QMFOperation _operation; + + public QMFCommandHeader(byte version, int seq, QMFOperation operation) + { + _version = version; + _seq = seq; + _operation = operation; + } + + public byte getVersion() + { + return _version; + } + + public int getSeq() + { + return _seq; + } + + public QMFOperation getOperation() + { + return _operation; + } + + public void encode(BBEncoder encoder) + { + encoder.writeUint8((short)'A'); + encoder.writeUint8((short)'M'); + encoder.writeInt8(_version); + encoder.writeUint8((short)_operation.getOpcode()); + encoder.writeInt32(_seq); + } +} diff --git a/java/broker/src/main/java/org/apache/qpid/qmf/QMFEventClass.java b/java/broker/src/main/java/org/apache/qpid/qmf/QMFEventClass.java new file mode 100644 index 0000000000..ec471f18e8 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/qmf/QMFEventClass.java @@ -0,0 +1,42 @@ +/* + * + * 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.qmf; + +import java.util.List; + +public abstract class QMFEventClass extends QMFClass +{ + public QMFEventClass(String name, + byte[] schemaHash, + List<QMFProperty> properties, + List<QMFStatistic> statistics, List<QMFMethod> methods) + { + super(Type.EVENT, name, schemaHash, properties, statistics, methods); + } + + public QMFEventClass(String name, byte[] schemaHash) + { + super(Type.EVENT, name, schemaHash); + } + + abstract public QMFEventSeverity getSeverity(); + +}
\ No newline at end of file diff --git a/java/broker/src/main/java/org/apache/qpid/qmf/QMFEventCommand.java b/java/broker/src/main/java/org/apache/qpid/qmf/QMFEventCommand.java new file mode 100644 index 0000000000..d70c12db19 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/qmf/QMFEventCommand.java @@ -0,0 +1,49 @@ +/* + * + * 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.qmf; + +import org.apache.qpid.server.virtualhost.VirtualHost; +import org.apache.qpid.server.message.ServerMessage; +import org.apache.qpid.transport.codec.BBEncoder; + +public abstract class QMFEventCommand<T extends QMFEventClass> extends QMFCommand +{ + private final long _timestamp; + + protected QMFEventCommand() + { + super(new QMFCommandHeader((byte)'2',0, QMFOperation.EVENT)); + _timestamp = System.currentTimeMillis(); + } + + abstract public T getEventClass(); + + @Override + public void encode(final BBEncoder encoder) + { + super.encode(encoder); + encoder.writeStr8(getEventClass().getPackage().getName()); + encoder.writeStr8(getEventClass().getName()); + encoder.writeBin128(new byte[16]); + encoder.writeUint64(_timestamp * 1000000L); + encoder.writeUint8((short) getEventClass().getSeverity().ordinal()); + } +} diff --git a/java/broker/src/main/java/org/apache/qpid/qmf/QMFEventSeverity.java b/java/broker/src/main/java/org/apache/qpid/qmf/QMFEventSeverity.java new file mode 100644 index 0000000000..9f9c832732 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/qmf/QMFEventSeverity.java @@ -0,0 +1,33 @@ +/* + * + * 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.qmf; + +public enum QMFEventSeverity +{ + EMERGENCY, + ALERT, + CRITICAL, + ERROR, + WARN, + NOTICE, + INFORM, + DEBUG +} diff --git a/java/broker/src/main/java/org/apache/qpid/qmf/QMFGetQueryCommand.java b/java/broker/src/main/java/org/apache/qpid/qmf/QMFGetQueryCommand.java new file mode 100644 index 0000000000..8e8cb55a0d --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/qmf/QMFGetQueryCommand.java @@ -0,0 +1,182 @@ +/* + * + * 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.qmf; + +import org.apache.qpid.transport.codec.BBDecoder; +import org.apache.qpid.server.virtualhost.VirtualHost; +import org.apache.qpid.server.message.ServerMessage; +import org.apache.qpid.server.exchange.Exchange; +import org.apache.qpid.server.queue.BaseQueue; +import org.apache.qpid.server.registry.IApplicationRegistry; +import org.apache.qpid.AMQException; + +import java.util.*; + +public class QMFGetQueryCommand extends QMFCommand +{ + private Map<String, Object> _map; + + + public QMFGetQueryCommand(QMFCommandHeader header, BBDecoder decoder) + { + super(header); + + _map = decoder.readMap(); + } + + public void process(VirtualHost virtualHost, ServerMessage message) + { + String exchangeName = message.getMessageHeader().getReplyToExchange(); + String routingKey = message.getMessageHeader().getReplyToRoutingKey(); + + IApplicationRegistry appRegistry = virtualHost.getApplicationRegistry(); + QMFService service = appRegistry.getQMFService(); + + String className = (String) _map.get("_class"); + String packageName = (String) _map.get("_package"); + byte[] objectIdBytes = (byte[]) _map.get("_objectId"); + UUID objectId; + if(objectIdBytes != null) + { + long msb = 0; + long lsb = 0; + + for (int i = 0; i != 8; i++) + { + msb = (msb << 8) | (objectIdBytes[i] & 0xff); + } + for (int i = 8; i != 16; i++) + { + lsb = (lsb << 8) | (objectIdBytes[i] & 0xff); + } + objectId = new UUID(msb, lsb); + } + else + { + objectId = null; + } + + List<QMFCommand> commands = new ArrayList<QMFCommand>(); + final long sampleTime = System.currentTimeMillis() * 1000000l; + + Collection<QMFPackage> packages; + + if(packageName != null && packageName.length() != 0) + { + QMFPackage qmfPackage = service.getPackage(packageName); + if(qmfPackage == null) + { + packages = Collections.EMPTY_LIST; + } + else + { + packages = Collections.singleton(qmfPackage); + } + } + else + { + packages = service.getSupportedSchemas(); + } + + for(QMFPackage qmfPackage : packages) + { + + Collection<QMFClass> qmfClasses; + + if(className != null && className.length() != 0) + { + QMFClass qmfClass = qmfPackage.getQMFClass(className); + if(qmfClass == null) + { + qmfClasses = Collections.EMPTY_LIST; + } + else + { + qmfClasses = Collections.singleton(qmfClass); + } + } + else + { + qmfClasses = qmfPackage.getClasses(); + } + + + for(QMFClass qmfClass : qmfClasses) + { + Collection<QMFObject> objects; + + if(objectId != null) + { + QMFObject obj = service.getObjectById(qmfClass, objectId); + if(obj == null) + { + objects = Collections.EMPTY_LIST; + } + else + { + objects = Collections.singleton(obj); + } + } + else + { + objects = service.getObjects(qmfClass); + } + + for(QMFObject object : objects) + { + + commands.add(object.asGetQueryResponseCmd(this, sampleTime)); + } + } + + + } + + + commands.add( new QMFCommandCompletionCommand(this)); + + + for(QMFCommand cmd : commands) + { + + + QMFMessage responseMessage = new QMFMessage(routingKey, cmd); + + Exchange exchange = virtualHost.getExchangeRegistry().getExchange(exchangeName); + + ArrayList<? extends BaseQueue> queues = exchange.route(responseMessage); + + for(BaseQueue q : queues) + { + try + { + q.enqueue(responseMessage); + } + catch (AMQException e) + { + e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. + } + } + } + } + +}
\ No newline at end of file diff --git a/java/broker/src/main/java/org/apache/qpid/qmf/QMFMessage.java b/java/broker/src/main/java/org/apache/qpid/qmf/QMFMessage.java new file mode 100644 index 0000000000..c250b2c011 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/qmf/QMFMessage.java @@ -0,0 +1,205 @@ +/* + * + * 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.qmf; + +import org.apache.qpid.server.message.*; +import org.apache.qpid.transport.codec.BBEncoder; + +import java.nio.ByteBuffer; +import java.util.Set; + +public class QMFMessage implements ServerMessage, InboundMessage, AMQMessageHeader +{ + + private ByteBuffer _content; + private String _routingKey; + + public QMFMessage(String routingKey, QMFCommand command) + { + this(routingKey, new QMFCommand[] { command }); + } + + + public QMFMessage(String routingKey, QMFCommand[] commands) + { + _routingKey = routingKey; + BBEncoder encoder = new BBEncoder(256); + + for(QMFCommand cmd : commands) + { + cmd.encode(encoder); + } + + + _content = encoder.buffer(); + } + + public String getRoutingKey() + { + return _routingKey; + } + + public AMQMessageHeader getMessageHeader() + { + return this; + } + + public boolean isPersistent() + { + return false; + } + + public boolean isRedelivered() + { + return false; + } + + public long getSize() + { + return _content.limit(); + } + + public boolean isImmediate() + { + return false; + } + + public String getCorrelationId() + { + return null; + } + + public long getExpiration() + { + return 0; + } + + public String getMessageId() + { + return null; + } + + public String getMimeType() + { + return null; + } + + public String getEncoding() + { + return null; + } + + public byte getPriority() + { + return 4; + } + + public long getTimestamp() + { + return 0; + } + + public String getType() + { + return null; + } + + public String getReplyTo() + { + return null; + } + + public String getReplyToExchange() + { + return null; + } + + public String getReplyToRoutingKey() + { + return null; + } + + public Object getHeader(String name) + { + return null; + } + + public boolean containsHeaders(Set<String> names) + { + return false; + } + + public boolean containsHeader(String name) + { + return false; + } + + public MessageReference newReference() + { + return new QMFMessageReference(this); + } + + public Long getMessageNumber() + { + return null; + } + + public long getArrivalTime() + { + return 0; + } + + public int getContent(ByteBuffer buf, int offset) + { + ByteBuffer src = _content.duplicate(); + _content.position(offset); + _content = _content.slice(); + int len = _content.remaining(); + if(len > buf.remaining()) + { + len = buf.remaining(); + } + + buf.put(src); + + return len; + } + + private class QMFMessageReference extends MessageReference<QMFMessage> + { + public QMFMessageReference(QMFMessage message) + { + super(message); + } + + protected void onReference(QMFMessage message) + { + + } + + protected void onRelease(QMFMessage message) + { + + } + } + +} diff --git a/java/broker/src/main/java/org/apache/qpid/qmf/QMFMethod.java b/java/broker/src/main/java/org/apache/qpid/qmf/QMFMethod.java new file mode 100644 index 0000000000..63e8fa6a1e --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/qmf/QMFMethod.java @@ -0,0 +1,157 @@ +/* + * + * 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.qmf; + +import org.apache.qpid.transport.codec.Encoder; +import org.apache.qpid.transport.codec.BBDecoder; + +import java.util.LinkedHashMap; +import java.util.List; +import java.util.ArrayList; + +public abstract class QMFMethod<T extends QMFObject> +{ + private final LinkedHashMap<String,Object> _map = new LinkedHashMap<String,Object>(); + private final List<Argument> _arguments = new ArrayList<Argument>(); + + private static final String NAME = "name"; + private static final String TYPE = "type"; + private static final String REF_PACKAGE = "refPackage"; + private static final String REF_CLASS = "refClass"; + private static final String UNIT = "unit"; + private static final String MIN = "min"; + private static final String MAX = "max"; + private static final String MAX_LENGTH = "maxlen"; + private static final String DESCRIPTION = "desc"; + private static final String DEFAULT = "default"; + private static final String DIRECTION = "dir"; + private static final String ARG_COUNT = "argCount"; + + + + public enum Direction + { + I, + O, + IO; + } + + public class Argument + { + private final LinkedHashMap<String,Object> _map = new LinkedHashMap<String,Object>(); + + public Argument(String name, QMFType type) + { + _map.put(NAME, name); + _map.put(TYPE, type.codeValue()); + } + + public void setRefPackage(String refPackage) + { + _map.put(REF_PACKAGE, refPackage); + } + + public void setRefClass(String refClass) + { + _map.put(REF_CLASS, refClass); + } + + public void setUnit(String unit) + { + _map.put(UNIT, unit); + } + + public void setMax(Number max) + { + _map.put(MAX, max); + } + + public void setMin(Number min) + { + _map.put(MIN, min); + } + + public void setMaxLength(int len) + { + _map.put(MAX_LENGTH, len); + } + + public void setDefault(Object dflt) + { + _map.put(DEFAULT, dflt); + } + + public void setDescription(String desc) + { + _map.put(DESCRIPTION, desc); + } + + public void setDirection(Direction direction) + { + _map.put(DIRECTION, direction.toString()); + } + + public void encode(Encoder encoder) + { + encoder.writeMap(_map); + } + + public String getName() + { + return (String) _map.get(NAME); + } + } + + public QMFMethod(String name, String description) + { + _map.put(NAME, name); + _map.put(ARG_COUNT, 0); + if(description != null) + { + _map.put(DESCRIPTION, description); + } + + } + + abstract public QMFMethodInvocation<T> parse(final BBDecoder decoder); + + protected void addArgument(Argument arg) + { + _arguments.add(arg); + _map.put(ARG_COUNT, _arguments.size()); + } + + + public void encode(Encoder encoder) + { + encoder.writeMap(_map); + for(Argument arg : _arguments) + { + arg.encode(encoder); + } + } + + public String getName() + { + return (String) _map.get(NAME); + } +} diff --git a/java/broker/src/main/java/org/apache/qpid/qmf/QMFMethodInvocation.java b/java/broker/src/main/java/org/apache/qpid/qmf/QMFMethodInvocation.java new file mode 100644 index 0000000000..5348c2783f --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/qmf/QMFMethodInvocation.java @@ -0,0 +1,26 @@ +/* + * + * 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.qmf; + +public interface QMFMethodInvocation<T extends QMFObject> +{ + QMFMethodResponseCommand execute(T obj, QMFMethodRequestCommand cmd); +} diff --git a/java/broker/src/main/java/org/apache/qpid/qmf/QMFMethodRequestCommand.java b/java/broker/src/main/java/org/apache/qpid/qmf/QMFMethodRequestCommand.java new file mode 100644 index 0000000000..cf27e4b970 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/qmf/QMFMethodRequestCommand.java @@ -0,0 +1,88 @@ +/* + * + * 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.qmf; + +import org.apache.qpid.transport.codec.BBDecoder; +import org.apache.qpid.server.virtualhost.VirtualHost; +import org.apache.qpid.server.message.ServerMessage; +import org.apache.qpid.server.exchange.Exchange; +import org.apache.qpid.server.queue.BaseQueue; +import org.apache.qpid.AMQException; + +import java.util.UUID; +import java.util.ArrayList; + +public class QMFMethodRequestCommand extends QMFCommand +{ + private QMFMethodInvocation _methodInstance; + private QMFObject _object; + + public QMFMethodRequestCommand(final QMFCommandHeader header, final BBDecoder decoder, final QMFService qmfService) + { + super(header); + UUID objectId = decoder.readUuid(); + String packageName = decoder.readStr8(); + String className = decoder.readStr8(); + byte[] hash = decoder.readBin128(); + String methodName = decoder.readStr8(); + + QMFPackage qmfPackage = qmfService.getPackage(packageName); + QMFClass qmfClass = qmfPackage.getQMFClass(className); + _object = qmfService.getObjectById(qmfClass, objectId); + QMFMethod method = qmfClass.getMethod(methodName); + _methodInstance = method.parse(decoder); + + } + + public void process(final VirtualHost virtualHost, final ServerMessage message) + { + String exchangeName = message.getMessageHeader().getReplyToExchange(); + String queueName = message.getMessageHeader().getReplyToRoutingKey(); + + QMFCommand[] commands = new QMFCommand[2]; + commands[0] = _methodInstance.execute(_object, this); + commands[1] = new QMFCommandCompletionCommand(this); + + Exchange exchange = virtualHost.getExchangeRegistry().getExchange(exchangeName); + + for(QMFCommand cmd : commands) + { + QMFMessage responseMessage = new QMFMessage(queueName, cmd); + + + ArrayList<? extends BaseQueue> queues = exchange.route(responseMessage); + + + for(BaseQueue q : queues) + { + try + { + q.enqueue(responseMessage); + } + catch (AMQException e) + { + e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. + } + } + } + + } +} diff --git a/java/broker/src/main/java/org/apache/qpid/qmf/QMFMethodResponseCommand.java b/java/broker/src/main/java/org/apache/qpid/qmf/QMFMethodResponseCommand.java new file mode 100644 index 0000000000..529b04ebdb --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/qmf/QMFMethodResponseCommand.java @@ -0,0 +1,43 @@ +/* + * + * 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.qmf; + +import org.apache.qpid.server.virtualhost.VirtualHost; +import org.apache.qpid.server.message.ServerMessage; +import org.apache.qpid.transport.codec.BBEncoder; + +public class QMFMethodResponseCommand extends QMFCommand +{ + public QMFMethodResponseCommand(final QMFMethodRequestCommand cmd) + { + super( new QMFCommandHeader(cmd.getHeader().getVersion(), + cmd.getHeader().getSeq(), + QMFOperation.METHOD_RESPONSE)); + } + + @Override + public void encode(final BBEncoder encoder) + { + super.encode(encoder); + encoder.writeUint32(0); + encoder.writeStr16("OK"); + } +} diff --git a/java/broker/src/main/java/org/apache/qpid/qmf/QMFObject.java b/java/broker/src/main/java/org/apache/qpid/qmf/QMFObject.java new file mode 100644 index 0000000000..d126717fc8 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/qmf/QMFObject.java @@ -0,0 +1,76 @@ +/* + * + * 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.qmf; + +import java.util.UUID; + +public abstract class QMFObject<C extends QMFClass, D extends QMFObject.Delegate> +{ + private long _deleteTime; + + public interface Delegate + { + UUID getId(); + long getCreateTime(); + } + + + private D _delegate; + + protected QMFObject(D delegate) + { + _delegate = delegate; + } + + public D getDelegate() + { + return _delegate; + } + + abstract public C getQMFClass(); + + public final UUID getId() + { + return _delegate.getId(); + } + + public final long getCreateTime() + { + return _delegate.getCreateTime(); + } + + public final void setDeleteTime() + { + _deleteTime = System.currentTimeMillis(); + } + + public final long getDeleteTime() + { + return _deleteTime; + } + + + + abstract public QMFCommand asConfigInfoCmd(long sampleTime); + abstract public QMFCommand asInstrumentInfoCmd(long sampleTime); + abstract public QMFCommand asGetQueryResponseCmd(final QMFGetQueryCommand queryCommand, long sampleTime); + +} diff --git a/java/broker/src/main/java/org/apache/qpid/qmf/QMFObjectClass.java b/java/broker/src/main/java/org/apache/qpid/qmf/QMFObjectClass.java new file mode 100644 index 0000000000..fefdecb8d7 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/qmf/QMFObjectClass.java @@ -0,0 +1,44 @@ +/* + * + * 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.qmf; + +import java.util.List; + +public abstract class QMFObjectClass<T extends QMFObject, S extends QMFObject.Delegate> extends QMFClass +{ + public QMFObjectClass(String name, + byte[] schemaHash, + List<QMFProperty> properties, + List<QMFStatistic> statistics, List<QMFMethod> methods) + { + super(QMFClass.Type.OBJECT, name, schemaHash, properties, statistics, methods); + } + + public QMFObjectClass(String name, byte[] schemaHash) + { + super(QMFClass.Type.OBJECT, name, schemaHash); + } + + + public abstract T newInstance(S delegate); + + +} diff --git a/java/broker/src/main/java/org/apache/qpid/qmf/QMFOperation.java b/java/broker/src/main/java/org/apache/qpid/qmf/QMFOperation.java new file mode 100644 index 0000000000..6736b5d460 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/qmf/QMFOperation.java @@ -0,0 +1,67 @@ +/* + * + * 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.qmf; + +public enum QMFOperation +{ + + + BROKER_REQUEST('B'), + BROKER_RESPONSE('b'), // This message contains a broker response, sent from the broker in response to a broker request message. + COMMAND_COMPLETION('z'), // This message is sent to indicate the completion of a request. + CLASS_QUERY('Q'), // Class query messages are used by a management console to request a list of schema classes that are known by the management broker. + CLASS_INDICATION('q'), // Sent by the management broker, a class indication notifies the peer of the existence of a schema class. + SCHEMA_REQUEST('S'), // Schema request messages are used to request the full schema details for a class. + SCHEMA_RESPONSE('s'), // Schema response message contain a full description of the schema for a class. + HEARTBEAT_INDEICATION('h'), // This message is published once per publish-interval. It can be used by a client to positively determine which objects did not change during the interval (since updates are not published for objects with no changes). + CONFIG_INDICATION('c'), + INSTRUMENTATION_INDICATION('i'), + GET_QUERY_RESPONSE('g'), // This message contains a content record. Content records contain the values of all properties or statistics in an object. Such records are broadcast on a periodic interval if 1) a change has been made in the value of one of the elements, or 2) if a new management client has bound a queue to the management exchange. + GET_QUERY('G'), // Sent by a management console, a get query requests that the management broker provide content indications for all objects that match the query criteria. + METHOD_REQUEST('M'), // This message contains a method request. + METHOD_RESPONSE('m'), // This message contains a method result. + PACKAGE_QUERY('P'), // This message contains a schema package query request, requesting that the broker dump the list of known packages + PACKAGE_INDICATION('p'), // This message contains a schema package indication, identifying a package known by the broker + AGENT_ATTACH_REUQEST('A'), // This message is sent by a remote agent when it wishes to attach to a management broker + AGENT_ATTACH_RESPONSE('a'), // The management broker sends this response if an attaching remote agent is permitted to join + CONSOLE_ADDED_INDICATION('x'), // This message is sent to all remote agents by the management broker when a new console binds to the management exchange + EVENT('e') + ; + + + private final char _opcode; + + private static final QMFOperation[] OP_CODES = new QMFOperation[256]; + + + QMFOperation(char opcode) + { + _opcode = opcode; + } + + + public char getOpcode() + { + return _opcode; + } + +} diff --git a/java/broker/src/main/java/org/apache/qpid/qmf/QMFPackage.java b/java/broker/src/main/java/org/apache/qpid/qmf/QMFPackage.java new file mode 100644 index 0000000000..681e64b799 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/qmf/QMFPackage.java @@ -0,0 +1,67 @@ +/* + * + * 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.qmf; + +import java.util.Collection; +import java.util.Map; +import java.util.HashMap; + +public class QMFPackage +{ + private final String _name; + private final Map<String, QMFClass> _classes = new HashMap<String, QMFClass>(); + + public QMFPackage(String name) + { + _name = name; + } + + public QMFPackage(String name, Collection<QMFClass> classes) + { + this(name); + setClasses(classes); + } + + protected void setClasses(Collection<QMFClass> classes) + { + for(QMFClass qmfClass : classes) + { + qmfClass.setPackage(this); + _classes.put(qmfClass.getName(), qmfClass); + } + } + + public String getName() + { + return _name; + } + + public Collection<QMFClass> getClasses() + { + return _classes.values(); + } + + public QMFClass getQMFClass(String className) + { + return _classes.get(className); + } +} diff --git a/java/broker/src/main/java/org/apache/qpid/qmf/QMFPackageIndicationCommand.java b/java/broker/src/main/java/org/apache/qpid/qmf/QMFPackageIndicationCommand.java new file mode 100644 index 0000000000..7053b80655 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/qmf/QMFPackageIndicationCommand.java @@ -0,0 +1,46 @@ +/* + * + * 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.qmf; + +import org.apache.qpid.server.virtualhost.VirtualHost; +import org.apache.qpid.server.message.ServerMessage; +import org.apache.qpid.transport.codec.BBEncoder; + +public class QMFPackageIndicationCommand extends QMFCommand +{ + private String _supportedSchema; + + public QMFPackageIndicationCommand(QMFPackageQueryCommand qmfPackageQueryCommand, String supportedSchema) + { + super( new QMFCommandHeader(qmfPackageQueryCommand.getHeader().getVersion(), + qmfPackageQueryCommand.getHeader().getSeq(), + QMFOperation.PACKAGE_INDICATION)); + _supportedSchema = supportedSchema; + + } + + public void encode(BBEncoder encoder) + { + super.encode(encoder); + encoder.writeStr8(_supportedSchema); + } +} diff --git a/java/broker/src/main/java/org/apache/qpid/qmf/QMFPackageQueryCommand.java b/java/broker/src/main/java/org/apache/qpid/qmf/QMFPackageQueryCommand.java new file mode 100644 index 0000000000..6defd088de --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/qmf/QMFPackageQueryCommand.java @@ -0,0 +1,86 @@ +/* + * + * 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.qmf; + +import org.apache.qpid.transport.codec.BBDecoder; +import org.apache.qpid.server.virtualhost.VirtualHost; +import org.apache.qpid.server.message.ServerMessage; +import org.apache.qpid.server.exchange.Exchange; +import org.apache.qpid.server.queue.BaseQueue; +import org.apache.qpid.server.registry.IApplicationRegistry; +import org.apache.qpid.AMQException; + +import java.util.ArrayList; +import java.util.Collection; + +public class QMFPackageQueryCommand extends QMFCommand +{ + public QMFPackageQueryCommand(QMFCommandHeader header, BBDecoder decoder) + { + super(header); + } + + public void process(VirtualHost virtualHost, ServerMessage message) + { + String exchangeName = message.getMessageHeader().getReplyToExchange(); + String routingKey = message.getMessageHeader().getReplyToRoutingKey(); + + + IApplicationRegistry appRegistry = virtualHost.getApplicationRegistry(); + QMFService service = appRegistry.getQMFService(); + + Collection<QMFPackage> supportedSchemas = service.getSupportedSchemas(); + + QMFCommand[] commands = new QMFCommand[ supportedSchemas.size() + 1 ]; + + int i = 0; + for(QMFPackage p : supportedSchemas) + { + commands[i++] = new QMFPackageIndicationCommand(this, p.getName()); + } + commands[ commands.length - 1 ] = new QMFCommandCompletionCommand(this); + + + for(QMFCommand cmd : commands) + { + + QMFMessage responseMessage = new QMFMessage(routingKey, cmd); + + Exchange exchange = virtualHost.getExchangeRegistry().getExchange(exchangeName); + + ArrayList<? extends BaseQueue> queues = exchange.route(responseMessage); + + + for(BaseQueue q : queues) + { + try + { + q.enqueue(responseMessage); + } + catch (AMQException e) + { + e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. + } + } + } + } +} diff --git a/java/broker/src/main/java/org/apache/qpid/qmf/QMFProperty.java b/java/broker/src/main/java/org/apache/qpid/qmf/QMFProperty.java new file mode 100644 index 0000000000..5748722afe --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/qmf/QMFProperty.java @@ -0,0 +1,123 @@ +/* + * + * 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.qmf; + +import org.apache.qpid.transport.codec.Encoder; + +import java.util.Map; +import java.util.HashMap; +import java.util.LinkedHashMap; + +public class QMFProperty +{ + private final Map<String, Object> _map = new LinkedHashMap<String, Object>(); + private static final String NAME = "name"; + private static final String TYPE = "type"; + private static final String ACCESS = "access"; + private static final String INDEX = "index"; + private static final String OPTIONAL = "optional"; + private static final String REF_PACKAGE = "refPackage"; + private static final String REF_CLASS = "refClass"; + private static final String UNIT = "unit"; + private static final String MIN = "min"; + private static final String MAX = "max"; + private static final String MAX_LENGTH = "maxlen"; + private static final String DESCRIPTION = "desc"; + + + public static enum AccessCode + { + RC, + RW, + RO; + + public int codeValue() + { + return ordinal()+1; + } + } + + public QMFProperty(String name, QMFType type, AccessCode accessCode, boolean index, boolean optional) + { + _map.put(NAME, name); + _map.put(TYPE, type.codeValue()); + _map.put(ACCESS, accessCode.codeValue()); + _map.put(INDEX, index ? 1 : 0); + _map.put(OPTIONAL, optional ? 1 :0); + } + + + public void setQMFClass(QMFClass qmfClass) + { + /* _map.put(REF_CLASS, qmfClass.getName()); + _map.put(REF_PACKAGE, qmfClass.getPackage().getName());*/ + } + + public void setReferencedClass(String refClass) + { + _map.put(REF_CLASS, refClass); + } + + public void setReferencedPackage(String refPackage) + { + _map.put(REF_CLASS, refPackage); + } + + + public String getName() + { + return (String) _map.get(NAME); + } + + + public void setUnit(String unit) + { + _map.put(UNIT, unit); + } + + public void setMin(Number min) + { + _map.put(MIN, min); + } + + public void setMax(Number max) + { + _map.put(MAX, max); + } + + public void setMaxLength(int maxlen) + { + _map.put(MAX_LENGTH, maxlen); + } + + + public void setDescription(String description) + { + _map.put(DESCRIPTION, description); + } + + public void encode(Encoder encoder) + { + encoder.writeMap(_map); + } + +} diff --git a/java/broker/src/main/java/org/apache/qpid/qmf/QMFSchemaRequestCommand.java b/java/broker/src/main/java/org/apache/qpid/qmf/QMFSchemaRequestCommand.java new file mode 100644 index 0000000000..3141676f10 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/qmf/QMFSchemaRequestCommand.java @@ -0,0 +1,88 @@ +/* + * + * 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.qmf; + +import org.apache.qpid.transport.codec.BBDecoder; +import org.apache.qpid.server.virtualhost.VirtualHost; +import org.apache.qpid.server.message.ServerMessage; +import org.apache.qpid.server.registry.IApplicationRegistry; +import org.apache.qpid.server.exchange.Exchange; +import org.apache.qpid.server.queue.BaseQueue; +import org.apache.qpid.AMQException; + +import java.util.Collection; +import java.util.ArrayList; + +public class QMFSchemaRequestCommand extends QMFCommand +{ + private final String _packageName; + private final String _className; + private final byte[] _hash; + + public QMFSchemaRequestCommand(QMFCommandHeader header, BBDecoder decoder) + { + super(header); + _packageName = decoder.readStr8(); + _className = decoder.readStr8(); + _hash = decoder.readBin128(); + } + + public void process(VirtualHost virtualHost, ServerMessage message) + { + String exchangeName = message.getMessageHeader().getReplyToExchange(); + String routingKey = message.getMessageHeader().getReplyToRoutingKey(); + + IApplicationRegistry appRegistry = virtualHost.getApplicationRegistry(); + QMFService service = appRegistry.getQMFService(); + + QMFPackage qmfPackage = service.getPackage(_packageName); + QMFClass qmfClass = qmfPackage.getQMFClass( _className ); + + QMFCommand[] commands = new QMFCommand[2]; + commands[0] = new QMFSchemaResponseCommand(this, qmfClass); + commands[ 1 ] = new QMFCommandCompletionCommand(this); + + + + Exchange exchange = virtualHost.getExchangeRegistry().getExchange(exchangeName); + + for(QMFCommand cmd : commands) + { + QMFMessage responseMessage = new QMFMessage(routingKey, cmd); + + + ArrayList<? extends BaseQueue> queues = exchange.route(responseMessage); + + for(BaseQueue q : queues) + { + try + { + q.enqueue(responseMessage); + } + catch (AMQException e) + { + e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. + } + } + } + } +} diff --git a/java/broker/src/main/java/org/apache/qpid/qmf/QMFSchemaResponseCommand.java b/java/broker/src/main/java/org/apache/qpid/qmf/QMFSchemaResponseCommand.java new file mode 100644 index 0000000000..fea2430130 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/qmf/QMFSchemaResponseCommand.java @@ -0,0 +1,83 @@ +/* + * + * 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.qmf; + +import org.apache.qpid.server.virtualhost.VirtualHost; +import org.apache.qpid.server.message.ServerMessage; +import org.apache.qpid.transport.codec.BBEncoder; + +import java.util.Collection; + +public class QMFSchemaResponseCommand extends QMFCommand +{ + private final QMFClass _qmfClass; + + + public QMFSchemaResponseCommand(QMFSchemaRequestCommand qmfSchemaRequestCommand, QMFClass qmfClass) + { + super(new QMFCommandHeader(qmfSchemaRequestCommand.getHeader().getVersion(), + qmfSchemaRequestCommand.getHeader().getSeq(), + QMFOperation.SCHEMA_RESPONSE)); + _qmfClass = qmfClass; + } + + @Override + public void encode(BBEncoder encoder) + { + super.encode(encoder); + encoder.writeUint8(_qmfClass.getType().getValue()); + encoder.writeStr8(_qmfClass.getPackage().getName()); + encoder.writeStr8(_qmfClass.getName()); + encoder.writeBin128(_qmfClass.getSchemaHash()); + + Collection<QMFProperty> props = _qmfClass.getProperties(); + Collection<QMFStatistic> stats = _qmfClass.getStatistics(); + Collection<QMFMethod> methods = _qmfClass.getMethods(); + + encoder.writeUint16(props.size()); + if(_qmfClass.getType() == QMFClass.Type.OBJECT) + { + encoder.writeUint16(stats.size()); + encoder.writeUint16(methods.size()); + } + + for(QMFProperty prop : props) + { + prop.encode(encoder); + } + + if(_qmfClass.getType() == QMFClass.Type.OBJECT) + { + + for(QMFStatistic stat : stats) + { + stat.encode(encoder); + } + + for(QMFMethod method : methods) + { + method.encode(encoder); + } + } + + } +} diff --git a/java/broker/src/main/java/org/apache/qpid/qmf/QMFService.java b/java/broker/src/main/java/org/apache/qpid/qmf/QMFService.java new file mode 100644 index 0000000000..6a1c24b5a7 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/qmf/QMFService.java @@ -0,0 +1,1583 @@ +/* + * + * 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.qmf; + +import org.apache.qpid.qmf.schema.BrokerSchema; +import org.apache.qpid.server.configuration.*; +import org.apache.qpid.server.registry.IApplicationRegistry; + +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.CopyOnWriteArrayList; + +public class QMFService implements ConfigStore.ConfigEventListener +{ + + + private IApplicationRegistry _applicationRegistry; + private ConfigStore _configStore; + + + private final Map<String, QMFPackage> _supportedSchemas = new HashMap<String, QMFPackage>(); + private static final Map<String, ConfigObjectType> _qmfClassMapping = new HashMap<String, ConfigObjectType>(); + + static + { + _qmfClassMapping.put("system", SystemConfigType.getInstance()); + _qmfClassMapping.put("broker", BrokerConfigType.getInstance()); + _qmfClassMapping.put("vhost", VirtualHostConfigType.getInstance()); + _qmfClassMapping.put("exchange", ExchangeConfigType.getInstance()); + _qmfClassMapping.put("queue", QueueConfigType.getInstance()); + _qmfClassMapping.put("binding", BindingConfigType.getInstance()); + _qmfClassMapping.put("connection", ConnectionConfigType.getInstance()); + _qmfClassMapping.put("session", SessionConfigType.getInstance()); + _qmfClassMapping.put("subscription", SubscriptionConfigType.getInstance()); + _qmfClassMapping.put("link", LinkConfigType.getInstance()); + _qmfClassMapping.put("bridge", BridgeConfigType.getInstance()); + } + + private final Map<ConfigObjectType, ConfigObjectAdapter> _adapterMap = + new HashMap<ConfigObjectType, ConfigObjectAdapter>(); + private final Map<ConfigObjectType,QMFClass> _classMap = + new HashMap<ConfigObjectType,QMFClass>(); + + + private final ConcurrentHashMap<QMFClass,ConcurrentHashMap<ConfiguredObject, QMFObject>> _managedObjects = + new ConcurrentHashMap<QMFClass,ConcurrentHashMap<ConfiguredObject, QMFObject>>(); + + private final ConcurrentHashMap<QMFClass,ConcurrentHashMap<UUID, QMFObject>> _managedObjectsById = + new ConcurrentHashMap<QMFClass,ConcurrentHashMap<UUID, QMFObject>>(); + + private static final BrokerSchema PACKAGE = BrokerSchema.getPackage(); + + public static interface Listener + { + public void objectCreated(QMFObject obj); + public void objectDeleted(QMFObject obj); + } + + private final CopyOnWriteArrayList<Listener> _listeners = new CopyOnWriteArrayList<Listener>(); + + abstract class ConfigObjectAdapter<Q extends QMFObject<S,D>, S extends QMFObjectClass<Q,D>, D extends QMFObject.Delegate, T extends ConfigObjectType<T,C>, C extends ConfiguredObject<T,C>> + { + private final T _type; + private final S _qmfClass; + + + protected ConfigObjectAdapter(final T type, final S qmfClass) + { + _type = type; + _qmfClass = qmfClass; + _adapterMap.put(type,this); + _classMap.put(type,qmfClass); + } + + public T getType() + { + return _type; + } + + public S getQMFClass() + { + return _qmfClass; + } + + protected final Q newInstance(D delegate) + { + return _qmfClass.newInstance(delegate); + } + + public abstract Q createQMFObject(C configObject); + } + + private ConfigObjectAdapter<BrokerSchema.SystemObject, + BrokerSchema.SystemClass, + BrokerSchema.SystemDelegate, + SystemConfigType, + SystemConfig> _systemObjectAdapter = + new ConfigObjectAdapter<BrokerSchema.SystemObject, + BrokerSchema.SystemClass, + BrokerSchema.SystemDelegate, + SystemConfigType, + SystemConfig>(SystemConfigType.getInstance(), + PACKAGE.getQMFClassInstance(BrokerSchema.SystemClass.class)) + { + + + public BrokerSchema.SystemObject createQMFObject( + final SystemConfig configObject) + { + return newInstance(new SystemDelegate(configObject)); + } + }; + + private ConfigObjectAdapter<BrokerSchema.BrokerObject, + BrokerSchema.BrokerClass, + BrokerSchema.BrokerDelegate, + BrokerConfigType, + BrokerConfig> _brokerObjectAdapter = + new ConfigObjectAdapter<BrokerSchema.BrokerObject, + BrokerSchema.BrokerClass, + BrokerSchema.BrokerDelegate, + BrokerConfigType, + BrokerConfig>(BrokerConfigType.getInstance(), + PACKAGE.getQMFClassInstance(BrokerSchema.BrokerClass.class)) + { + + public BrokerSchema.BrokerObject createQMFObject( + final BrokerConfig configObject) + { + return newInstance(new BrokerDelegate(configObject)); + } + }; + + private ConfigObjectAdapter<BrokerSchema.VhostObject, + BrokerSchema.VhostClass, + BrokerSchema.VhostDelegate, + VirtualHostConfigType, + VirtualHostConfig> _vhostObjectAdapter = + new ConfigObjectAdapter<BrokerSchema.VhostObject, + BrokerSchema.VhostClass, + BrokerSchema.VhostDelegate, + VirtualHostConfigType, + VirtualHostConfig>(VirtualHostConfigType.getInstance(), + PACKAGE.getQMFClassInstance(BrokerSchema.VhostClass.class)) + { + + public BrokerSchema.VhostObject createQMFObject( + final VirtualHostConfig configObject) + { + return newInstance(new VhostDelegate(configObject)); + } + }; + + + private ConfigObjectAdapter<BrokerSchema.ExchangeObject, + BrokerSchema.ExchangeClass, + BrokerSchema.ExchangeDelegate, + ExchangeConfigType, + ExchangeConfig> _exchangeObjectAdapter = + new ConfigObjectAdapter<BrokerSchema.ExchangeObject, + BrokerSchema.ExchangeClass, + BrokerSchema.ExchangeDelegate, + ExchangeConfigType, + ExchangeConfig>(ExchangeConfigType.getInstance(), + PACKAGE.getQMFClassInstance(BrokerSchema.ExchangeClass.class)) + { + + public BrokerSchema.ExchangeObject createQMFObject( + final ExchangeConfig configObject) + { + return newInstance(new ExchangeDelegate(configObject)); + } + }; + + + private ConfigObjectAdapter<BrokerSchema.QueueObject, + BrokerSchema.QueueClass, + BrokerSchema.QueueDelegate, + QueueConfigType, + QueueConfig> _queueObjectAdapter = + new ConfigObjectAdapter<BrokerSchema.QueueObject, + BrokerSchema.QueueClass, + BrokerSchema.QueueDelegate, + QueueConfigType, + QueueConfig>(QueueConfigType.getInstance(), + PACKAGE.getQMFClassInstance(BrokerSchema.QueueClass.class)) + { + + public BrokerSchema.QueueObject createQMFObject( + final QueueConfig configObject) + { + return newInstance(new QueueDelegate(configObject)); + } + }; + + + private ConfigObjectAdapter<BrokerSchema.BindingObject, + BrokerSchema.BindingClass, + BrokerSchema.BindingDelegate, + BindingConfigType, + BindingConfig> _bindingObjectAdapter = + new ConfigObjectAdapter<BrokerSchema.BindingObject, + BrokerSchema.BindingClass, + BrokerSchema.BindingDelegate, + BindingConfigType, + BindingConfig>(BindingConfigType.getInstance(), + PACKAGE.getQMFClassInstance(BrokerSchema.BindingClass.class)) + { + + public BrokerSchema.BindingObject createQMFObject( + final BindingConfig configObject) + { + return newInstance(new BindingDelegate(configObject)); + } + }; + + + private ConfigObjectAdapter<BrokerSchema.ConnectionObject, + BrokerSchema.ConnectionClass, + BrokerSchema.ConnectionDelegate, + ConnectionConfigType, + ConnectionConfig> _connectionObjectAdapter = + new ConfigObjectAdapter<BrokerSchema.ConnectionObject, + BrokerSchema.ConnectionClass, + BrokerSchema.ConnectionDelegate, + ConnectionConfigType, + ConnectionConfig>(ConnectionConfigType.getInstance(), + PACKAGE.getQMFClassInstance(BrokerSchema.ConnectionClass.class)) + { + + public BrokerSchema.ConnectionObject createQMFObject( + final ConnectionConfig configObject) + { + return newInstance(new ConnectionDelegate(configObject)); + } + }; + + + private ConfigObjectAdapter<BrokerSchema.SessionObject, + BrokerSchema.SessionClass, + BrokerSchema.SessionDelegate, + SessionConfigType, + SessionConfig> _sessionObjectAdapter = + new ConfigObjectAdapter<BrokerSchema.SessionObject, + BrokerSchema.SessionClass, + BrokerSchema.SessionDelegate, + SessionConfigType, + SessionConfig>(SessionConfigType.getInstance(), + PACKAGE.getQMFClassInstance(BrokerSchema.SessionClass.class)) + { + + public BrokerSchema.SessionObject createQMFObject( + final SessionConfig configObject) + { + return newInstance(new SessionDelegate(configObject)); + } + }; + + private ConfigObjectAdapter<BrokerSchema.SubscriptionObject, + BrokerSchema.SubscriptionClass, + BrokerSchema.SubscriptionDelegate, + SubscriptionConfigType, + SubscriptionConfig> _subscriptionObjectAdapter = + new ConfigObjectAdapter<BrokerSchema.SubscriptionObject, + BrokerSchema.SubscriptionClass, + BrokerSchema.SubscriptionDelegate, + SubscriptionConfigType, + SubscriptionConfig>(SubscriptionConfigType.getInstance(), + PACKAGE.getQMFClassInstance(BrokerSchema.SubscriptionClass.class)) + { + + public BrokerSchema.SubscriptionObject createQMFObject( + final SubscriptionConfig configObject) + { + return newInstance(new SubscriptionDelegate(configObject)); + } + }; + + + private ConfigObjectAdapter<BrokerSchema.LinkObject, + BrokerSchema.LinkClass, + BrokerSchema.LinkDelegate, + LinkConfigType, + LinkConfig> _linkObjectAdapter = + new ConfigObjectAdapter<BrokerSchema.LinkObject, + BrokerSchema.LinkClass, + BrokerSchema.LinkDelegate, + LinkConfigType, + LinkConfig>(LinkConfigType.getInstance(), + PACKAGE.getQMFClassInstance(BrokerSchema.LinkClass.class)) + { + + public BrokerSchema.LinkObject createQMFObject( + final LinkConfig configObject) + { + return newInstance(new LinkDelegate(configObject)); + } + }; + + + private ConfigObjectAdapter<BrokerSchema.BridgeObject, + BrokerSchema.BridgeClass, + BrokerSchema.BridgeDelegate, + BridgeConfigType, + BridgeConfig> _bridgeObjectAdapter = + new ConfigObjectAdapter<BrokerSchema.BridgeObject, + BrokerSchema.BridgeClass, + BrokerSchema.BridgeDelegate, + BridgeConfigType, + BridgeConfig>(BridgeConfigType.getInstance(), + PACKAGE.getQMFClassInstance(BrokerSchema.BridgeClass.class)) + { + + public BrokerSchema.BridgeObject createQMFObject( + final BridgeConfig configObject) + { + return newInstance(new BridgeDelegate(configObject)); + } + }; + + + + public QMFService(ConfigStore configStore, IApplicationRegistry applicationRegistry) + { + _configStore = configStore; + _applicationRegistry = applicationRegistry; + registerSchema(PACKAGE); + + for(ConfigObjectType v : _qmfClassMapping.values()) + { + configStore.addConfigEventListener(v, this); + } + init(); + } + + public void close() + { + _managedObjects.clear(); + _managedObjectsById.clear(); + _classMap.clear(); + _adapterMap.clear(); + _supportedSchemas.clear(); + } + + + public void registerSchema(QMFPackage qmfPackage) + { + _supportedSchemas.put(qmfPackage.getName(), qmfPackage); + } + + + public Collection<QMFPackage> getSupportedSchemas() + { + return _supportedSchemas.values(); + } + + public QMFPackage getPackage(String aPackage) + { + return _supportedSchemas.get(aPackage); + } + + public void onEvent(final ConfiguredObject object, final ConfigStore.Event evt) + { + + switch (evt) + { + case CREATED: + manageObject(object); + break; + + case DELETED: + unmanageObject(object); + break; + } + } + + public QMFObject getObjectById(QMFClass qmfclass, UUID id) + { + ConcurrentHashMap<UUID, QMFObject> map = _managedObjectsById.get(qmfclass); + if(map != null) + { + return map.get(id); + } + else + { + return null; + } + } + + private void unmanageObject(final ConfiguredObject object) + { + final QMFClass qmfClass = _classMap.get(object.getConfigType()); + + ConcurrentHashMap<ConfiguredObject, QMFObject> classObjects = _managedObjects.get(qmfClass); + if(classObjects != null) + { + QMFObject qmfObject = classObjects.remove(object); + if(qmfObject != null) + { + _managedObjectsById.get(qmfClass).remove(object.getId()); + objectRemoved(qmfObject); + } + } + } + + private void manageObject(final ConfiguredObject object) + { + ConfigObjectAdapter adapter = _adapterMap.get(object.getConfigType()); + QMFObject qmfObject = adapter.createQMFObject(object); + final QMFClass qmfClass = qmfObject.getQMFClass(); + ConcurrentHashMap<ConfiguredObject, QMFObject> classObjects = _managedObjects.get(qmfClass); + + if(classObjects == null) + { + classObjects = new ConcurrentHashMap<ConfiguredObject, QMFObject>(); + if(_managedObjects.putIfAbsent(qmfClass, classObjects) != null) + { + classObjects = _managedObjects.get(qmfClass); + } + } + + ConcurrentHashMap<UUID, QMFObject> classObjectsById = _managedObjectsById.get(qmfClass); + if(classObjectsById == null) + { + classObjectsById = new ConcurrentHashMap<UUID, QMFObject>(); + if(_managedObjectsById.putIfAbsent(qmfClass, classObjectsById) != null) + { + classObjectsById = _managedObjectsById.get(qmfClass); + } + } + + classObjectsById.put(object.getId(),qmfObject); + + if(classObjects.putIfAbsent(object, qmfObject) == null); + { + objectAdded(qmfObject); + } + } + + private void objectRemoved(final QMFObject qmfObject) + { + qmfObject.setDeleteTime(); + for(Listener l : _listeners) + { + l.objectDeleted(qmfObject); + } + } + + private void objectAdded(final QMFObject qmfObject) + { + for(Listener l : _listeners) + { + l.objectCreated(qmfObject); + } + } + + public void addListener(Listener l) + { + _listeners.add(l); + } + + public void removeListener(Listener l) + { + _listeners.remove(l); + } + + + private void init() + { + for(QMFClass qmfClass : PACKAGE.getClasses()) + { + ConfigObjectType configType = getConfigType(qmfClass); + if(configType != null) + { + Collection<ConfiguredObject> objects = _configStore.getConfiguredObjects(configType); + for(ConfiguredObject object : objects) + { + manageObject(object); + } + } + } + } + + public Collection<QMFObject> getObjects(QMFClass qmfClass) + { + ConcurrentHashMap<ConfiguredObject, QMFObject> classObjects = _managedObjects.get(qmfClass); + if(classObjects != null) + { + return classObjects.values(); + } + else + { + return Collections.EMPTY_SET; + } + } + + private QMFObject adapt(final ConfiguredObject object) + { + if(object == null) + { + return null; + } + + QMFClass qmfClass = _classMap.get(object.getConfigType()); + ConcurrentHashMap<ConfiguredObject, QMFObject> classObjects = _managedObjects.get(qmfClass); + if(classObjects != null) + { + QMFObject qmfObject = classObjects.get(object); + if(qmfObject != null) + { + return qmfObject; + } + } + + return _adapterMap.get(object.getConfigType()).createQMFObject(object); + } + + private ConfigObjectType getConfigType(final QMFClass qmfClass) + { + return _qmfClassMapping.get(qmfClass.getName()); + } + + private static class SystemDelegate implements BrokerSchema.SystemDelegate + { + private final SystemConfig _obj; + + public SystemDelegate(final SystemConfig obj) + { + _obj = obj; + } + + public UUID getSystemId() + { + return _obj.getId(); + } + + public String getOsName() + { + return _obj.getOperatingSystemName(); + } + + public String getNodeName() + { + return _obj.getNodeName(); + } + + public String getRelease() + { + return _obj.getOSRelease(); + } + + public String getVersion() + { + return _obj.getOSVersion(); + } + + public String getMachine() + { + return _obj.getOSArchitecture(); + } + + public UUID getId() + { + return _obj.getId(); + } + + public long getCreateTime() + { + return _obj.getCreateTime(); + } + } + + private class BrokerDelegate implements BrokerSchema.BrokerDelegate + { + private final BrokerConfig _obj; + + public BrokerDelegate(final BrokerConfig obj) + { + _obj = obj; + } + + public BrokerSchema.SystemObject getSystemRef() + { + return (BrokerSchema.SystemObject) adapt(_obj.getSystem()); + } + + public Integer getPort() + { + return _obj.getPort(); + } + + public Integer getWorkerThreads() + { + return _obj.getWorkerThreads(); + } + + public Integer getMaxConns() + { + return _obj.getMaxConnections(); + } + + public Integer getConnBacklog() + { + return _obj.getConnectionBacklogLimit(); + } + + public Long getStagingThreshold() + { + return _obj.getStagingThreshold(); + } + + public Integer getMgmtPubInterval() + { + return _obj.getManagementPublishInterval(); + } + + public String getVersion() + { + return _obj.getVersion(); + } + + public String getDataDir() + { + return _obj.getDataDirectory(); + } + + public Long getUptime() + { + return (System.currentTimeMillis() - _obj.getCreateTime()) * 1000000L; + } + + public BrokerSchema.BrokerClass.EchoMethodResponseCommand echo(final BrokerSchema.BrokerClass.EchoMethodResponseCommandFactory factory, + final Long sequence, + final String body) + { + return factory.createResponseCommand(sequence, body); + } + + public BrokerSchema.BrokerClass.ConnectMethodResponseCommand connect(final BrokerSchema.BrokerClass.ConnectMethodResponseCommandFactory factory, + final String host, + final Long port, + final Boolean durable, + final String authMechanism, + final String username, + final String password, + final String transport) + { + _obj.createBrokerConnection(transport, host, port.intValue(), durable, authMechanism, username, password); + + return factory.createResponseCommand(); + } + + public BrokerSchema.BrokerClass.QueueMoveMessagesMethodResponseCommand queueMoveMessages(final BrokerSchema.BrokerClass.QueueMoveMessagesMethodResponseCommandFactory factory, + final String srcQueue, + final String destQueue, + final Long qty) + { + // todo + throw new UnsupportedOperationException(); + } + + public UUID getId() + { + return _obj.getId(); + } + + public long getCreateTime() + { + return _obj.getCreateTime(); + } + } + + private class VhostDelegate implements BrokerSchema.VhostDelegate + { + private final VirtualHostConfig _obj; + + public VhostDelegate(final VirtualHostConfig obj) + { + _obj = obj; + } + + public BrokerSchema.BrokerObject getBrokerRef() + { + return (BrokerSchema.BrokerObject) adapt(_obj.getBroker()); + } + + public String getName() + { + return _obj.getName(); + } + + public String getFederationTag() + { + return _obj.getFederationTag(); + } + + public UUID getId() + { + return _obj.getId(); + } + + public long getCreateTime() + { + return _obj.getCreateTime(); + } + } + + private class ExchangeDelegate implements BrokerSchema.ExchangeDelegate + { + private final ExchangeConfig _obj; + + public ExchangeDelegate(final ExchangeConfig obj) + { + _obj = obj; + } + + public BrokerSchema.VhostObject getVhostRef() + { + return (BrokerSchema.VhostObject) adapt(_obj.getVirtualHost()); + } + + public String getName() + { + return _obj.getName(); + } + + public String getType() + { + return _obj.getType().getName().toString(); + } + + public Boolean getDurable() + { + return _obj.isDurable(); + } + + public Boolean getAutoDelete() + { + return _obj.isAutoDelete(); + } + + public BrokerSchema.ExchangeObject getAltExchange() + { + if(_obj.getAlternateExchange() != null) + { + return (BrokerSchema.ExchangeObject) adapt(_obj.getAlternateExchange()); + } + else + { + return null; + } + } + + public Map getArguments() + { + return _obj.getArguments(); + } + + public Long getProducerCount() + { + // TODO + return 0l; + } + + public Long getProducerCountHigh() + { + // TODO + return 0l; + } + + public Long getProducerCountLow() + { + // TODO + return 0l; + } + + public Long getBindingCount() + { + return _obj.getBindingCount(); + } + + public Long getBindingCountHigh() + { + return _obj.getBindingCountHigh(); + } + + public Long getBindingCountLow() + { + // TODO + return 0l; + } + + public Long getMsgReceives() + { + return _obj.getMsgReceives(); + } + + public Long getMsgDrops() + { + return getMsgReceives() - getMsgRoutes(); + } + + public Long getMsgRoutes() + { + return _obj.getMsgRoutes(); + } + + public Long getByteReceives() + { + return _obj.getByteReceives(); + } + + public Long getByteDrops() + { + return getByteReceives() - getByteRoutes(); + } + + public Long getByteRoutes() + { + return _obj.getByteRoutes(); + } + + public UUID getId() + { + return _obj.getId(); + } + + public long getCreateTime() + { + return _obj.getCreateTime(); + } + } + + private class QueueDelegate implements BrokerSchema.QueueDelegate + { + private final QueueConfig _obj; + + public QueueDelegate(final QueueConfig obj) + { + _obj = obj; + } + + public BrokerSchema.VhostObject getVhostRef() + { + return (BrokerSchema.VhostObject) adapt(_obj.getVirtualHost()); + } + + public String getName() + { + return _obj.getName(); + } + + public Boolean getDurable() + { + return _obj.isDurable(); + } + + public Boolean getAutoDelete() + { + return _obj.isAutoDelete(); + } + + public Boolean getExclusive() + { + return _obj.isExclusive(); + } + + public BrokerSchema.ExchangeObject getAltExchange() + { + if(_obj.getAlternateExchange() != null) + { + return (BrokerSchema.ExchangeObject) adapt(_obj.getAlternateExchange()); + } + else + { + return null; + } + } + + public Long getMsgTotalEnqueues() + { + return _obj.getReceivedMessageCount(); + } + + public Long getMsgTotalDequeues() + { + return _obj.getMessageDequeueCount(); + } + + public Long getMsgTxnEnqueues() + { + // TODO + return 0l; + } + + public Long getMsgTxnDequeues() + { + // TODO + return 0l; + } + + public Long getMsgPersistEnqueues() + { + return _obj.getPersistentMsgEnqueues(); + } + + public Long getMsgPersistDequeues() + { + return _obj.getPersistentMsgDequeues(); + } + + public Long getMsgDepth() + { + return (long) _obj.getMessageCount(); + } + + public Long getByteDepth() + { + return _obj.getQueueDepth(); + } + + public Long getByteTotalEnqueues() + { + return _obj.getTotalEnqueueSize(); + } + + public Long getByteTotalDequeues() + { + return _obj.getTotalDequeueSize(); + } + + public Long getByteTxnEnqueues() + { + // TODO + return 0l; + } + + public Long getByteTxnDequeues() + { + // TODO + return 0l; + } + + public Long getBytePersistEnqueues() + { + return _obj.getPersistentByteEnqueues(); + } + + public Long getBytePersistDequeues() + { + return _obj.getPersistentByteDequeues(); + } + + public Long getConsumerCount() + { + return (long) _obj.getConsumerCount(); + } + + public Long getConsumerCountHigh() + { + // TODO + return 0l; + } + + public Long getConsumerCountLow() + { + // TODO + return 0l; + } + + public Long getBindingCount() + { + return (long) _obj.getBindingCount(); + } + + public Long getBindingCountHigh() + { + return (long) _obj.getBindingCountHigh(); + } + + public Long getBindingCountLow() + { + // TODO + return 0l; + } + + public Long getUnackedMessages() + { + // TODO + return 0l; + } + + public Long getUnackedMessagesHigh() + { + // TODO + return 0l; + } + + public Long getUnackedMessagesLow() + { + // TODO + return 0l; + } + + public Long getMessageLatencySamples() + { + // TODO + return 0l; + } + + public Long getMessageLatencyMin() + { + // TODO + return 0l; + } + + public Long getMessageLatencyMax() + { + // TODO + return 0l; + } + + public Long getMessageLatencyAverage() + { + // TODO + return 0l; + } + + public BrokerSchema.QueueClass.PurgeMethodResponseCommand purge(final BrokerSchema.QueueClass.PurgeMethodResponseCommandFactory factory, + final Long request) + { + _obj.purge(request); + return factory.createResponseCommand(); + } + + public Map getArguments() + { + return _obj.getArguments(); + } + + public UUID getId() + { + return _obj.getId(); + } + + public long getCreateTime() + { + return _obj.getCreateTime(); + } + } + + private class BindingDelegate implements BrokerSchema.BindingDelegate + { + private final BindingConfig _obj; + + public BindingDelegate(final BindingConfig obj) + { + _obj = obj; + } + + public BrokerSchema.ExchangeObject getExchangeRef() + { + return (BrokerSchema.ExchangeObject) adapt(_obj.getExchange()); + } + + public BrokerSchema.QueueObject getQueueRef() + { + return (BrokerSchema.QueueObject) adapt(_obj.getQueue()); + } + + public String getBindingKey() + { + return _obj.getBindingKey(); + } + + public Map getArguments() + { + return _obj.getArguments(); + } + + public String getOrigin() + { + return _obj.getOrigin(); + } + + public Long getMsgMatched() + { + // TODO + return _obj.getMatches(); + } + + public UUID getId() + { + return _obj.getId(); + } + + public long getCreateTime() + { + return _obj.getCreateTime(); + } + } + + private class ConnectionDelegate implements BrokerSchema.ConnectionDelegate + { + private final ConnectionConfig _obj; + + public ConnectionDelegate(final ConnectionConfig obj) + { + _obj = obj; + } + + public BrokerSchema.VhostObject getVhostRef() + { + return (BrokerSchema.VhostObject) adapt(_obj.getVirtualHost()); + } + + public String getAddress() + { + return _obj.getAddress(); + } + + public Boolean getIncoming() + { + return _obj.isIncoming(); + } + + public Boolean getSystemConnection() + { + return _obj.isSystemConnection(); + } + + public Boolean getFederationLink() + { + return _obj.isFederationLink(); + } + + public String getAuthIdentity() + { + return _obj.getAuthId(); + } + + public String getRemoteProcessName() + { + return _obj.getRemoteProcessName(); + } + + public Long getRemotePid() + { + Integer remotePID = _obj.getRemotePID(); + return remotePID == null ? null : (long) remotePID; + } + + public Long getRemoteParentPid() + { + Integer remotePPID = _obj.getRemoteParentPID(); + return remotePPID == null ? null : (long) remotePPID; + + } + + public Boolean getClosing() + { + return false; + } + + public Long getFramesFromClient() + { + // TODO + return 0l; + } + + public Long getFramesToClient() + { + // TODO + return 0l; + } + + public Long getBytesFromClient() + { + // TODO + return 0l; + } + + public Long getBytesToClient() + { + // TODO + return 0l; + } + + public BrokerSchema.ConnectionClass.CloseMethodResponseCommand close(final BrokerSchema.ConnectionClass.CloseMethodResponseCommandFactory factory) + { + //todo + throw new UnsupportedOperationException(); + } + + public UUID getId() + { + return _obj.getId(); + } + + public long getCreateTime() + { + // TODO + return 0; + } + } + + private class SessionDelegate implements BrokerSchema.SessionDelegate + { + private final SessionConfig _obj; + + public SessionDelegate(final SessionConfig obj) + { + _obj = obj; + } + + public BrokerSchema.VhostObject getVhostRef() + { + return (BrokerSchema.VhostObject) adapt(_obj.getVirtualHost()); + } + + public String getName() + { + return _obj.getSessionName(); + } + + public Integer getChannelId() + { + return _obj.getChannel(); + } + + public BrokerSchema.ConnectionObject getConnectionRef() + { + return (BrokerSchema.ConnectionObject) adapt(_obj.getConnectionConfig()); + } + + public Long getDetachedLifespan() + { + return _obj.getDetachedLifespan(); + } + + public Boolean getAttached() + { + return _obj.isAttached(); + } + + public Long getExpireTime() + { + return _obj.getExpiryTime(); + } + + public Long getMaxClientRate() + { + return _obj.getMaxClientRate(); + } + + public Long getFramesOutstanding() + { + // TODO + return 0l; + } + + public Long getTxnStarts() + { + // TODO + return 0l; + } + + public Long getTxnCommits() + { + // TODO + return 0l; + } + + public Long getTxnRejects() + { + // TODO + return 0l; + } + + public Long getTxnCount() + { + // TODO + return 0l; + } + + public Long getClientCredit() + { + // TODO + return 0l; + } + + public BrokerSchema.SessionClass.SolicitAckMethodResponseCommand solicitAck(final BrokerSchema.SessionClass.SolicitAckMethodResponseCommandFactory factory) + { + //todo + throw new UnsupportedOperationException(); + } + + public BrokerSchema.SessionClass.DetachMethodResponseCommand detach(final BrokerSchema.SessionClass.DetachMethodResponseCommandFactory factory) + { + //todo + throw new UnsupportedOperationException(); + } + + public BrokerSchema.SessionClass.ResetLifespanMethodResponseCommand resetLifespan(final BrokerSchema.SessionClass.ResetLifespanMethodResponseCommandFactory factory) + { + //todo + throw new UnsupportedOperationException(); + } + + public BrokerSchema.SessionClass.CloseMethodResponseCommand close(final BrokerSchema.SessionClass.CloseMethodResponseCommandFactory factory) + { + //todo + throw new UnsupportedOperationException(); + } + + public UUID getId() + { + return _obj.getId(); + } + + public long getCreateTime() + { + // TODO + return 0; //To change body of implemented methods use File | Settings | File Templates. + } + } + + private class SubscriptionDelegate implements BrokerSchema.SubscriptionDelegate + { + private final SubscriptionConfig _obj; + + private SubscriptionDelegate(final SubscriptionConfig obj) + { + _obj = obj; + } + + + public BrokerSchema.SessionObject getSessionRef() + { + return (BrokerSchema.SessionObject) adapt(_obj.getSessionConfig()); + } + + public BrokerSchema.QueueObject getQueueRef() + { + return (BrokerSchema.QueueObject) adapt(_obj.getQueue()); + } + + public String getName() + { + return _obj.getName(); + } + + public Boolean getBrowsing() + { + return _obj.isBrowsing(); + } + + public Boolean getAcknowledged() + { + return _obj.isExplicitAcknowledge(); + } + + public Boolean getExclusive() + { + return _obj.isExclusive(); + } + + public String getCreditMode() + { + return _obj.getCreditMode(); + } + + public Map getArguments() + { + return _obj.getArguments(); + } + + public Long getDelivered() + { + // TODO + return 0l; + } + + public UUID getId() + { + return _obj.getId(); + } + + public long getCreateTime() + { + // TODO + return 0; //To change body of implemented methods use File | Settings | File Templates. + } + } + + private class BridgeDelegate implements BrokerSchema.BridgeDelegate + { + private final BridgeConfig _obj; + + private BridgeDelegate(final BridgeConfig obj) + { + _obj = obj; + } + + public BrokerSchema.LinkObject getLinkRef() + { + return (BrokerSchema.LinkObject) adapt(_obj.getLink()); + } + + public Integer getChannelId() + { + return _obj.getChannelId(); + } + + public Boolean getDurable() + { + return _obj.isDurable(); + } + + public String getSrc() + { + return _obj.getSource(); + } + + public String getDest() + { + return _obj.getDestination(); + } + + public String getKey() + { + return _obj.getKey(); + } + + public Boolean getSrcIsQueue() + { + return _obj.isQueueBridge(); + } + + public Boolean getSrcIsLocal() + { + return _obj.isLocalSource(); + } + + public String getTag() + { + return _obj.getTag(); + } + + public String getExcludes() + { + return _obj.getExcludes(); + } + + public Boolean getDynamic() + { + return _obj.isDynamic(); + } + + public Integer getSync() + { + return _obj.getAckBatching(); + } + + public BrokerSchema.BridgeClass.CloseMethodResponseCommand close(final BrokerSchema.BridgeClass.CloseMethodResponseCommandFactory factory) + { + return null; + } + + public UUID getId() + { + return _obj.getId(); + } + + public long getCreateTime() + { + return _obj.getCreateTime(); + } + } + + private class LinkDelegate implements BrokerSchema.LinkDelegate + { + private final LinkConfig _obj; + + private LinkDelegate(final LinkConfig obj) + { + _obj = obj; + } + + public BrokerSchema.VhostObject getVhostRef() + { + return (BrokerSchema.VhostObject) adapt(_obj.getVirtualHost()); + } + + public String getHost() + { + return _obj.getHost(); + } + + public Integer getPort() + { + return _obj.getPort(); + } + + public String getTransport() + { + return _obj.getTransport(); + } + + public Boolean getDurable() + { + return _obj.isDurable(); + } + + public String getState() + { + // TODO + return ""; + } + + public String getLastError() + { + // TODO + return ""; + } + + public BrokerSchema.LinkClass.CloseMethodResponseCommand close(final BrokerSchema.LinkClass.CloseMethodResponseCommandFactory factory) + { + _obj.close(); + return factory.createResponseCommand(); + } + + public BrokerSchema.LinkClass.BridgeMethodResponseCommand bridge(final BrokerSchema.LinkClass.BridgeMethodResponseCommandFactory factory, + final Boolean durable, + final String src, + final String dest, + final String key, + final String tag, + final String excludes, + final Boolean srcIsQueue, + final Boolean srcIsLocal, + final Boolean dynamic, + final Integer sync) + { + _obj.createBridge(durable, dynamic, srcIsQueue, srcIsLocal, src, dest, key, tag, excludes); + return factory.createResponseCommand(); + } + + public UUID getId() + { + return _obj.getId(); + } + + public long getCreateTime() + { + return _obj.getCreateTime(); + } + } + +} diff --git a/java/broker/src/main/java/org/apache/qpid/qmf/QMFStatistic.java b/java/broker/src/main/java/org/apache/qpid/qmf/QMFStatistic.java new file mode 100644 index 0000000000..89d650e03b --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/qmf/QMFStatistic.java @@ -0,0 +1,61 @@ +/* + * + * 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.qmf; + +import org.apache.qpid.transport.codec.Encoder; + +import java.util.LinkedHashMap; + +public class QMFStatistic +{ + private final LinkedHashMap<String,Object> _map = new LinkedHashMap<String,Object>(); + private static final String NAME = "name"; + private static final String TYPE = "type"; + private static final String UNIT = "unit"; + private static final String DESCRIPTION = "desc"; + + + public QMFStatistic(String name, QMFType type, String unit, String description) + { + _map.put(NAME, name); + _map.put(TYPE, type.codeValue()); + if(unit != null) + { + _map.put(UNIT, unit); + } + if(description != null) + { + _map.put(DESCRIPTION, description); + } + + } + + public void encode(Encoder encoder) + { + encoder.writeMap(_map); + } + + public String getName() + { + return (String) _map.get(NAME); + } +} diff --git a/java/broker/src/main/java/org/apache/qpid/qmf/QMFType.java b/java/broker/src/main/java/org/apache/qpid/qmf/QMFType.java new file mode 100644 index 0000000000..0e01c27db5 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/qmf/QMFType.java @@ -0,0 +1,53 @@ +/* + * + * 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.qmf; + +public enum QMFType +{ + + UINT8, + UINT16, + UINT32, + UINT64, + UNKNOWN, + STR8, + STR16, + ABSTIME, + DELTATIME, + OBJECTREFERENCE, + BOOLEAN, + FLOAT, + DOUBLE, + UUID, + MAP, + INT8, + INT16, + INT32, + INT64, + OBJECT, + LIST, + ARRAY; + + public int codeValue() + { + return ordinal()+1; + } +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/AMQChannel.java b/java/broker/src/main/java/org/apache/qpid/server/AMQChannel.java index 333c1b9cac..1b03ee2334 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/AMQChannel.java +++ b/java/broker/src/main/java/org/apache/qpid/server/AMQChannel.java @@ -20,45 +20,72 @@ */ package org.apache.qpid.server; -import java.util.*; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.ConcurrentMap; -import java.util.concurrent.ConcurrentHashMap; - import org.apache.log4j.Logger; + import org.apache.qpid.AMQException; -import org.apache.qpid.protocol.AMQConstant; -import org.apache.qpid.framing.*; -import org.apache.qpid.framing.abstraction.MessagePublishInfo; +import org.apache.qpid.framing.AMQMethodBody; +import org.apache.qpid.framing.AMQShortString; +import org.apache.qpid.framing.BasicContentHeaderProperties; +import org.apache.qpid.framing.ContentBody; +import org.apache.qpid.framing.ContentHeaderBody; +import org.apache.qpid.framing.FieldTable; +import org.apache.qpid.framing.MethodRegistry; import org.apache.qpid.framing.abstraction.ContentChunk; +import org.apache.qpid.framing.abstraction.MessagePublishInfo; +import org.apache.qpid.protocol.AMQConstant; import org.apache.qpid.server.ack.UnacknowledgedMessageMap; import org.apache.qpid.server.ack.UnacknowledgedMessageMapImpl; +import org.apache.qpid.server.configuration.ConfigStore; +import org.apache.qpid.server.configuration.ConfiguredObject; +import org.apache.qpid.server.configuration.ConnectionConfig; +import org.apache.qpid.server.configuration.SessionConfig; +import org.apache.qpid.server.configuration.SessionConfigType; import org.apache.qpid.server.exchange.Exchange; import org.apache.qpid.server.flow.FlowCreditManager; import org.apache.qpid.server.flow.Pre0_10CreditManager; -import org.apache.qpid.server.protocol.AMQProtocolSession; -import org.apache.qpid.server.queue.*; -import org.apache.qpid.server.subscription.Subscription; -import org.apache.qpid.server.subscription.SubscriptionFactoryImpl; -import org.apache.qpid.server.subscription.ClientDeliveryMethod; -import org.apache.qpid.server.subscription.RecordDeliveryMethod; -import org.apache.qpid.server.store.MessageStore; -import org.apache.qpid.server.store.StoredMessage; -import org.apache.qpid.server.txn.*; -import org.apache.qpid.server.message.ServerMessage; -import org.apache.qpid.server.message.AMQMessage; -import org.apache.qpid.server.message.MessageMetaData; -import org.apache.qpid.server.message.MessageReference; -import org.apache.qpid.server.registry.ApplicationRegistry; import org.apache.qpid.server.logging.LogActor; import org.apache.qpid.server.logging.LogSubject; -import org.apache.qpid.server.logging.messages.ChannelMessages; -import org.apache.qpid.server.logging.subjects.ChannelLogSubject; import org.apache.qpid.server.logging.actors.AMQPChannelActor; import org.apache.qpid.server.logging.actors.CurrentActor; +import org.apache.qpid.server.logging.messages.ChannelMessages; +import org.apache.qpid.server.logging.subjects.ChannelLogSubject; +import org.apache.qpid.server.message.AMQMessage; +import org.apache.qpid.server.message.MessageMetaData; +import org.apache.qpid.server.message.MessageReference; +import org.apache.qpid.server.message.ServerMessage; import org.apache.qpid.server.output.ProtocolOutputConverter; +import org.apache.qpid.server.protocol.AMQProtocolEngine; +import org.apache.qpid.server.protocol.AMQProtocolSession; +import org.apache.qpid.server.queue.AMQQueue; +import org.apache.qpid.server.queue.BaseQueue; +import org.apache.qpid.server.queue.IncomingMessage; +import org.apache.qpid.server.queue.QueueEntry; +import org.apache.qpid.server.registry.ApplicationRegistry; +import org.apache.qpid.server.store.MessageStore; +import org.apache.qpid.server.store.StoredMessage; +import org.apache.qpid.server.subscription.ClientDeliveryMethod; +import org.apache.qpid.server.subscription.RecordDeliveryMethod; +import org.apache.qpid.server.subscription.Subscription; +import org.apache.qpid.server.subscription.SubscriptionFactoryImpl; +import org.apache.qpid.server.txn.AutoCommitTransaction; +import org.apache.qpid.server.txn.LocalTransaction; +import org.apache.qpid.server.txn.ServerTransaction; +import org.apache.qpid.server.virtualhost.VirtualHost; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.SortedSet; +import java.util.TreeSet; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.atomic.AtomicBoolean; -public class AMQChannel +public class AMQChannel implements SessionConfig { public static final int DEFAULT_PREFETCH = 5000; @@ -123,6 +150,7 @@ public class AMQChannel private List<QueueEntry> _resendList = new ArrayList<QueueEntry>(); private static final AMQShortString IMMEDIATE_DELIVERY_REPLY_TEXT = new AMQShortString("Immediate delivery is not possible."); + private final UUID _id; public AMQChannel(AMQProtocolSession session, int channelId, MessageStore messageStore) throws AMQException @@ -132,15 +160,22 @@ public class AMQChannel _actor = new AMQPChannelActor(this, session.getLogActor().getRootMessageLogger()); _logSubject = new ChannelLogSubject(this); - + _id = getConfigStore().createId(); _actor.message(ChannelMessages.CHN_CREATE()); + getConfigStore().addConfiguredObject(this); + _messageStore = messageStore; // by default the session is non-transactional _transaction = new AutoCommitTransaction(_messageStore); } + public ConfigStore getConfigStore() + { + return getVirtualHost().getConfigStore(); + } + /** Sets this channel to be part of a local transaction */ public void setLocalTransactional() { @@ -220,7 +255,7 @@ public class AMQChannel try { - final ArrayList<AMQQueue> destinationQueues = _currentMessage.getDestinationQueues(); + final ArrayList<? extends BaseQueue> destinationQueues = _currentMessage.getDestinationQueues(); if(!checkMessageUserId(_currentMessage.getContentHeader())) { @@ -411,6 +446,8 @@ public class AMQChannel _logger.error("Caught AMQException whilst attempting to reque:" + e); } + getConfigStore().removeConfiguredObject(this); + } private void setClosing(boolean closing) @@ -970,10 +1007,10 @@ public class AMQChannel private class MessageDeliveryAction implements ServerTransaction.Action { private IncomingMessage _incommingMessage; - private ArrayList<AMQQueue> _destinationQueues; + private ArrayList<? extends BaseQueue> _destinationQueues; public MessageDeliveryAction(IncomingMessage currentMessage, - ArrayList<AMQQueue> destinationQueues) + ArrayList<? extends BaseQueue> destinationQueues) { _incommingMessage = currentMessage; _destinationQueues = destinationQueues; @@ -988,53 +1025,24 @@ public class AMQChannel final AMQMessage amqMessage = createAMQMessage(_incommingMessage); MessageReference ref = amqMessage.newReference(); - for(AMQQueue queue : _destinationQueues) + for(final BaseQueue queue : _destinationQueues) { + BaseQueue.PostEnqueueAction action; - QueueEntry entry = queue.enqueue(amqMessage); - queue.checkCapacity(AMQChannel.this); - - - if(immediate && !entry.getDeliveredToConsumer() && entry.acquire()) + if(immediate) { + action = new ImmediateAction(queue); + } + else + { + action = null; + } + queue.enqueue(amqMessage, action); - ServerTransaction txn = new LocalTransaction(_messageStore); - Collection<QueueEntry> entries = new ArrayList<QueueEntry>(1); - entries.add(entry); - final AMQMessage message = (AMQMessage) entry.getMessage(); - txn.dequeue(queue, entry.getMessage(), - new MessageAcknowledgeAction(entries) - { - @Override - public void postCommit() - { - try - { - final - ProtocolOutputConverter outputConverter = - _session.getProtocolOutputConverter(); - - outputConverter.writeReturn(message.getMessagePublishInfo(), - message.getContentHeaderBody(), - message, - _channelId, - AMQConstant.NO_CONSUMERS.getCode(), - IMMEDIATE_DELIVERY_REPLY_TEXT); - } - catch (AMQException e) - { - throw new RuntimeException(e); - } - super.postCommit(); - } - } - ); - txn.commit(); - - - - + if(queue instanceof AMQQueue) + { + ((AMQQueue)queue).checkCapacity(AMQChannel.this); } } @@ -1057,6 +1065,60 @@ public class AMQChannel // Maybe keep track of entries that were created and then delete them here in case of failure // to in memory enqueue } + + private class ImmediateAction implements BaseQueue.PostEnqueueAction + { + private final BaseQueue _queue; + + public ImmediateAction(BaseQueue queue) + { + _queue = queue; + } + + public void onEnqueue(QueueEntry entry) + { + if (!entry.getDeliveredToConsumer() && entry.acquire()) + { + + + ServerTransaction txn = new LocalTransaction(_messageStore); + Collection<QueueEntry> entries = new ArrayList<QueueEntry>(1); + entries.add(entry); + final AMQMessage message = (AMQMessage) entry.getMessage(); + txn.dequeue(_queue, entry.getMessage(), + new MessageAcknowledgeAction(entries) + { + @Override + public void postCommit() + { + try + { + final + ProtocolOutputConverter outputConverter = + _session.getProtocolOutputConverter(); + + outputConverter.writeReturn(message.getMessagePublishInfo(), + message.getContentHeaderBody(), + message, + _channelId, + AMQConstant.NO_CONSUMERS.getCode(), + IMMEDIATE_DELIVERY_REPLY_TEXT); + } + catch (AMQException e) + { + throw new RuntimeException(e); + } + super.postCommit(); + } + } + ); + txn.commit(); + + + } + + } + } } private class MessageAcknowledgeAction implements ServerTransaction.Action @@ -1163,7 +1225,7 @@ public class AMQChannel if(_blocking.compareAndSet(false,true)) { - _actor.message(_logSubject, ChannelMessages.CHN_FLOW_ENFORCED(queue.getName().toString())); + _actor.message(_logSubject, ChannelMessages.CHN_FLOW_ENFORCED(queue.getNameShortString().toString())); flow(false); } } @@ -1188,9 +1250,70 @@ public class AMQChannel AMQMethodBody responseBody = methodRegistry.createChannelFlowBody(flow); _session.writeFrame(responseBody.generateFrame(_channelId)); } - + public boolean getBlocking() { return _blocking.get(); } + + public VirtualHost getVirtualHost() + { + return getProtocolSession().getVirtualHost(); + } + + + public ConfiguredObject getParent() + { + return getVirtualHost(); + } + + public SessionConfigType getConfigType() + { + return SessionConfigType.getInstance(); + } + + public int getChannel() + { + return getChannelId(); + } + + public boolean isAttached() + { + return true; + } + + public long getDetachedLifespan() + { + return 0; + } + + public ConnectionConfig getConnectionConfig() + { + return (AMQProtocolEngine)getProtocolSession(); + } + + public Long getExpiryTime() + { + return null; + } + + public Long getMaxClientRate() + { + return null; + } + + public boolean isDurable() + { + return false; + } + + public UUID getId() + { + return _id; + } + + public String getSessionName() + { + return getConnectionConfig().getAddress() + "/" + getChannelId(); + } } diff --git a/java/broker/src/main/java/org/apache/qpid/server/binding/Binding.java b/java/broker/src/main/java/org/apache/qpid/server/binding/Binding.java new file mode 100644 index 0000000000..0b689c16a7 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/binding/Binding.java @@ -0,0 +1,117 @@ +/* + * + * 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.binding; + +import org.apache.qpid.server.exchange.Exchange; +import org.apache.qpid.server.queue.AMQQueue; + +import java.util.Collections; +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.atomic.AtomicLong; + +public class Binding +{ + private final String _bindingKey; + private final AMQQueue _queue; + private final Exchange _exchange; + private final Map<String, Object> _arguments; + private final UUID _id; + private final AtomicLong _matches = new AtomicLong(); + + Binding(UUID id, final String bindingKey, final AMQQueue queue, final Exchange exchange, final Map<String, Object> arguments) + { + _id = id; + _bindingKey = bindingKey; + _queue = queue; + _exchange = exchange; + _arguments = arguments == null ? Collections.EMPTY_MAP : Collections.unmodifiableMap(arguments); + } + + public UUID getId() + { + return _id; + } + + public String getBindingKey() + { + return _bindingKey; + } + + public AMQQueue getQueue() + { + return _queue; + } + + public Exchange getExchange() + { + return _exchange; + } + + public Map<String, Object> getArguments() + { + return _arguments; + } + + public void incrementMatches() + { + _matches.incrementAndGet(); + } + + public long getMatches() + { + return _matches.get(); + } + + boolean isDurable() + { + return _queue.isDurable() && _exchange.isDurable(); + } + + @Override + public boolean equals(final Object o) + { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + final Binding binding = (Binding) o; + + if (!_bindingKey.equals(binding._bindingKey)) return false; + if (!_exchange.equals(binding._exchange)) return false; + if (!_queue.equals(binding._queue)) return false; + + return true; + } + + @Override + public int hashCode() + { + int result = _bindingKey.hashCode(); + result = 31 * result + _queue.hashCode(); + result = 31 * result + _exchange.hashCode(); + return result; + } + + + + + +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/binding/BindingFactory.java b/java/broker/src/main/java/org/apache/qpid/server/binding/BindingFactory.java new file mode 100644 index 0000000000..e11af5d553 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/binding/BindingFactory.java @@ -0,0 +1,290 @@ +/* + * + * 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.binding; + +import org.apache.qpid.AMQException; +import org.apache.qpid.framing.AMQShortString; +import org.apache.qpid.framing.FieldTable; +import org.apache.qpid.server.configuration.BindingConfig; +import org.apache.qpid.server.configuration.BindingConfigType; +import org.apache.qpid.server.configuration.ConfigStore; +import org.apache.qpid.server.configuration.ConfiguredObject; +import org.apache.qpid.server.exchange.Exchange; +import org.apache.qpid.server.logging.actors.CurrentActor; +import org.apache.qpid.server.logging.messages.BindingMessages; +import org.apache.qpid.server.logging.subjects.BindingLogSubject; +import org.apache.qpid.server.queue.AMQQueue; +import org.apache.qpid.server.store.DurableConfigurationStore; +import org.apache.qpid.server.virtualhost.VirtualHost; + +import java.util.Collections; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +public class BindingFactory +{ + + private final VirtualHost _virtualHost; + private final DurableConfigurationStore.Source _configSource; + private final Exchange _defaultExchange; + + private final ConcurrentHashMap<BindingImpl, BindingImpl> _bindings = new ConcurrentHashMap<BindingImpl, BindingImpl>(); + + + public BindingFactory(final VirtualHost vhost) + { + this(vhost,vhost.getExchangeRegistry().getDefaultExchange()); + } + + public BindingFactory(final DurableConfigurationStore.Source configSource, final Exchange defaultExchange) + { + _configSource = configSource; + _defaultExchange = defaultExchange; + if(configSource instanceof VirtualHost) + { + _virtualHost = (VirtualHost) configSource; + } + else + { + _virtualHost = null; + } + } + + public VirtualHost getVirtualHost() + { + return _virtualHost; + } + + + + private final class BindingImpl extends Binding implements AMQQueue.Task, Exchange.Task, BindingConfig + { + private final BindingLogSubject _logSubject; + //TODO + private long _createTime = System.currentTimeMillis(); + + private BindingImpl(String bindingKey, final AMQQueue queue, final Exchange exchange, final Map<String, Object> arguments) + { + super(queue.getVirtualHost().getConfigStore().createId(),bindingKey, queue, exchange, arguments); + _logSubject = new BindingLogSubject(bindingKey,exchange,queue); + + } + + + public void doTask(final AMQQueue queue) throws AMQException + { + removeBinding(this); + } + + public void onClose(final Exchange exchange) + { + removeBinding(this); + } + + void logCreation() + { + CurrentActor.get().message(_logSubject, BindingMessages.BND_CREATED(String.valueOf(getArguments()), getArguments() != null && !getArguments().isEmpty())); + } + + void logDestruction() + { + CurrentActor.get().message(_logSubject, BindingMessages.BND_DELETED()); + } + + public String getOrigin() + { + return (String) getArguments().get("qpid.fed.origin"); + } + + public long getCreateTime() + { + return _createTime; + } + + public BindingConfigType getConfigType() + { + return BindingConfigType.getInstance(); + } + + public ConfiguredObject getParent() + { + return _virtualHost; + } + + public boolean isDurable() + { + return getQueue().isDurable() && getExchange().isDurable(); + } + + } + + + + public boolean addBinding(String bindingKey, AMQQueue queue, Exchange exchange, Map<String, Object> arguments) + { + return makeBinding(bindingKey, queue, exchange, arguments, false, false); + } + + + public boolean replaceBinding(final String bindingKey, + final AMQQueue queue, + final Exchange exchange, + final Map<String, Object> arguments) + { + return makeBinding(bindingKey, queue, exchange, arguments, false, true); + } + + private boolean makeBinding(String bindingKey, AMQQueue queue, Exchange exchange, Map<String, Object> arguments, boolean restore, boolean force) + { + assert queue != null; + if(bindingKey == null) + { + bindingKey = ""; + } + if(exchange == null) + { + exchange = _defaultExchange; + } + if(arguments == null) + { + arguments = Collections.EMPTY_MAP; + } + + BindingImpl b = new BindingImpl(bindingKey,queue,exchange,arguments); + BindingImpl existingMapping = _bindings.putIfAbsent(b,b); + if(existingMapping == null || force) + { + if(existingMapping != null) + { + removeBinding(existingMapping); + } + + if(b.isDurable() && !restore) + { + try + { + _configSource.getDurableConfigurationStore().bindQueue(exchange,new AMQShortString(bindingKey),queue,FieldTable.convertToFieldTable(arguments)); + } + catch (AMQException e) + { + throw new RuntimeException(e); + } + } + + queue.addQueueDeleteTask(b); + exchange.addCloseTask(b); + queue.addBinding(b); + exchange.addBinding(b); + getConfigStore().addConfiguredObject(b); + b.logCreation(); + return true; + } + else + { + return false; + } + + + } + + private ConfigStore getConfigStore() + { + return getVirtualHost().getConfigStore(); + } + + public void restoreBinding(final String bindingKey, final AMQQueue queue, final Exchange exchange, final Map<String, Object> argumentMap) + { + makeBinding(bindingKey,queue,exchange,argumentMap,true, false); + } + + public void removeBinding(final Binding b) + { + removeBinding(b.getBindingKey(), b.getQueue(), b.getExchange(), b.getArguments()); + } + + + public Binding removeBinding(String bindingKey, AMQQueue queue, Exchange exchange, Map<String, Object> arguments) + { + assert queue != null; + if(bindingKey == null) + { + bindingKey = ""; + } + if(exchange == null) + { + exchange = _defaultExchange; + } + if(arguments == null) + { + arguments = Collections.EMPTY_MAP; + } + + BindingImpl b = _bindings.remove(new BindingImpl(bindingKey,queue,exchange,arguments)); + + if(b != null) + { + exchange.removeBinding(b); + queue.removeBinding(b); + exchange.removeCloseTask(b); + queue.removeQueueDeleteTask(b); + + if(b.isDurable()) + { + try + { + _configSource.getDurableConfigurationStore().unbindQueue(exchange, + new AMQShortString(bindingKey), + queue, + FieldTable.convertToFieldTable(arguments)); + } + catch (AMQException e) + { + e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. + } + } + b.logDestruction(); + getConfigStore().removeConfiguredObject(b); + + } + + return b; + } + + public Binding getBinding(String bindingKey, AMQQueue queue, Exchange exchange, Map<String, Object> arguments) + { + assert queue != null; + if(bindingKey == null) + { + bindingKey = ""; + } + if(exchange == null) + { + exchange = _defaultExchange; + } + if(arguments == null) + { + arguments = Collections.EMPTY_MAP; + } + + BindingImpl b = new BindingImpl(bindingKey,queue,exchange,arguments); + return _bindings.get(b); + } +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/BindingConfig.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/BindingConfig.java new file mode 100644 index 0000000000..9414edcec4 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/configuration/BindingConfig.java @@ -0,0 +1,43 @@ +/* + * + * 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.configuration; + +import java.util.Map; + + +public interface BindingConfig extends ConfiguredObject<BindingConfigType, BindingConfig> +{ + + ExchangeConfig getExchange(); + + QueueConfig getQueue(); + + String getBindingKey(); + + Map<String, Object> getArguments(); + + String getOrigin(); + + long getCreateTime(); + + long getMatches(); +}
\ No newline at end of file diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/BindingConfigType.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/BindingConfigType.java new file mode 100644 index 0000000000..5cd064ff42 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/configuration/BindingConfigType.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.server.configuration; + +import org.apache.qpid.server.exchange.ExchangeType; + +import java.util.*; + +public final class BindingConfigType extends ConfigObjectType<BindingConfigType, BindingConfig> +{ + private static final List<BindingProperty<?>> BINDING_PROPERTIES = new ArrayList<BindingProperty<?>>(); + + public static interface BindingProperty<S> extends ConfigProperty<BindingConfigType, BindingConfig, S> + { + } + + private abstract static class BindingReadWriteProperty<S> extends ConfigProperty.ReadWriteConfigProperty<BindingConfigType, BindingConfig, S> implements BindingProperty<S> + { + public BindingReadWriteProperty(String name) + { + super(name); + BINDING_PROPERTIES.add(this); + } + } + + private abstract static class BindingReadOnlyProperty<S> extends ConfigProperty.ReadOnlyConfigProperty<BindingConfigType, BindingConfig, S> implements BindingProperty<S> + { + public BindingReadOnlyProperty(String name) + { + super(name); + BINDING_PROPERTIES.add(this); + } + } + + public static final BindingReadOnlyProperty<ExchangeConfig> EXCHANGE_PROPERTY = new BindingReadOnlyProperty<ExchangeConfig>("exchange") + { + public ExchangeConfig getValue(BindingConfig object) + { + return object.getExchange(); + } + }; + + public static final BindingReadOnlyProperty<QueueConfig> QUEUE_PROPERTY = new BindingReadOnlyProperty<QueueConfig>("queue") + { + public QueueConfig getValue(BindingConfig object) + { + return object.getQueue(); + } + }; + + public static final BindingReadOnlyProperty<String> BINDING_KEY_PROPERTY = new BindingReadOnlyProperty<String>("bindingKey") + { + public String getValue(BindingConfig object) + { + return object.getBindingKey(); + } + }; + + public static final BindingReadOnlyProperty<Map<String,Object>> ARGUMENTS = new BindingReadOnlyProperty<Map<String,Object>>("arguments") + { + public Map<String,Object> getValue(BindingConfig object) + { + return object.getArguments(); + } + }; + + public static final BindingReadOnlyProperty<String> ORIGIN_PROPERTY = new BindingReadOnlyProperty<String>("origin") + { + public String getValue(BindingConfig object) + { + return object.getOrigin(); + } + }; + + private static final BindingConfigType INSTANCE = new BindingConfigType(); + + private BindingConfigType() + { + } + + public Collection<BindingProperty<?>> getProperties() + { + return Collections.unmodifiableList(BINDING_PROPERTIES); + } + + public static BindingConfigType getInstance() + { + return INSTANCE; + } + + + +}
\ No newline at end of file diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/BridgeConfig.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/BridgeConfig.java new file mode 100644 index 0000000000..f999bf4578 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/configuration/BridgeConfig.java @@ -0,0 +1,50 @@ +/* + * + * 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.configuration; + +public interface BridgeConfig extends ConfiguredObject<BridgeConfigType, BridgeConfig> +{ + + boolean isDynamic(); + + boolean isQueueBridge(); + + boolean isLocalSource(); + + String getSource(); + + String getDestination(); + + String getKey(); + + String getTag(); + + String getExcludes(); + + LinkConfig getLink(); + + Integer getChannelId(); + + int getAckBatching(); + + long getCreateTime(); +}
\ No newline at end of file diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/BridgeConfigType.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/BridgeConfigType.java new file mode 100644 index 0000000000..a8d3cd9ec3 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/configuration/BridgeConfigType.java @@ -0,0 +1,169 @@ +/* + * + * 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.configuration; + +import org.apache.qpid.server.exchange.ExchangeType; + +import java.util.*; + +public final class BridgeConfigType extends ConfigObjectType<BridgeConfigType, BridgeConfig> +{ + private static final List<BridgeProperty<?>> BRIDGE_PROPERTIES = new ArrayList<BridgeProperty<?>>(); + + public static interface BridgeProperty<S> extends ConfigProperty<BridgeConfigType, BridgeConfig, S> + { + } + + private abstract static class BridgeReadWriteProperty<S> extends ConfigProperty.ReadWriteConfigProperty<BridgeConfigType, BridgeConfig, S> implements BridgeProperty<S> + { + public BridgeReadWriteProperty(String name) + { + super(name); + BRIDGE_PROPERTIES.add(this); + } + } + + private abstract static class BridgeReadOnlyProperty<S> extends ConfigProperty.ReadOnlyConfigProperty<BridgeConfigType, BridgeConfig, S> implements BridgeProperty<S> + { + public BridgeReadOnlyProperty(String name) + { + super(name); + BRIDGE_PROPERTIES.add(this); + } + } + + public static final BridgeReadOnlyProperty<LinkConfig> LINK_PROPERTY = new BridgeReadOnlyProperty<LinkConfig>("link") + { + public LinkConfig getValue(BridgeConfig object) + { + return object.getLink(); + } + }; + + public static final BridgeReadOnlyProperty<Integer> CHANNEL_ID_PROPERTY = new BridgeReadOnlyProperty<Integer>("channelId") + { + public Integer getValue(BridgeConfig object) + { + return object.getChannelId(); + } + }; + + public static final BridgeReadOnlyProperty<Boolean> DURABLE_PROPERTY = new BridgeReadOnlyProperty<Boolean>("durable") + { + public Boolean getValue(BridgeConfig object) + { + return object.isDurable(); + } + }; + + public static final BridgeReadOnlyProperty<String> SOURCE_PROPERTY = new BridgeReadOnlyProperty<String>("source") + { + public String getValue(BridgeConfig object) + { + return object.getSource(); + } + }; + + public static final BridgeReadOnlyProperty<String> DESTINATION_PROPERTY = new BridgeReadOnlyProperty<String>("destination") + { + public String getValue(BridgeConfig object) + { + return object.getDestination(); + } + }; + + public static final BridgeReadOnlyProperty<String> KEY_PROPERTY = new BridgeReadOnlyProperty<String>("key") + { + public String getValue(BridgeConfig object) + { + return object.getKey(); + } + }; + + public static final BridgeReadOnlyProperty<Boolean> QUEUE_BRIDGE_PROPERTY = new BridgeReadOnlyProperty<Boolean>("queueBridge") + { + public Boolean getValue(BridgeConfig object) + { + return object.isQueueBridge(); + } + }; + + public static final BridgeReadOnlyProperty<Boolean> LOCAL_SOURCE_PROPERTY = new BridgeReadOnlyProperty<Boolean>("localSource") + { + public Boolean getValue(BridgeConfig object) + { + return object.isLocalSource(); + } + }; + + public static final BridgeReadOnlyProperty<String> TAG_PROPERTY = new BridgeReadOnlyProperty<String>("tag") + { + public String getValue(BridgeConfig object) + { + return object.getTag(); + } + }; + + public static final BridgeReadOnlyProperty<String> EXCLUDES_PROPERTY = new BridgeReadOnlyProperty<String>("excludes") + { + public String getValue(BridgeConfig object) + { + return object.getExcludes(); + } + }; + + public static final BridgeReadOnlyProperty<Boolean> DYNAMIC_PROPERTY = new BridgeReadOnlyProperty<Boolean>("dynamic") + { + public Boolean getValue(BridgeConfig object) + { + return object.isDynamic(); + } + }; + + public static final BridgeReadOnlyProperty<Integer> ACK_BATCHING_PROPERTY = new BridgeReadOnlyProperty<Integer>("ackBatching") + { + public Integer getValue(BridgeConfig object) + { + return object.getAckBatching(); + } + }; + + + private static final BridgeConfigType INSTANCE = new BridgeConfigType(); + + private BridgeConfigType() + { + } + + public Collection<BridgeProperty<?>> getProperties() + { + return Collections.unmodifiableList(BRIDGE_PROPERTIES); + } + + public static BridgeConfigType getInstance() + { + return INSTANCE; + } + + + +}
\ No newline at end of file diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/BrokerConfig.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/BrokerConfig.java new file mode 100644 index 0000000000..4f74a72344 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/configuration/BrokerConfig.java @@ -0,0 +1,59 @@ +/* + * + * 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.configuration; + + +public interface BrokerConfig extends ConfiguredObject<BrokerConfigType,BrokerConfig> +{ + void setSystem(SystemConfig system); + + SystemConfig getSystem(); + + Integer getPort(); + + Integer getWorkerThreads(); + + Integer getMaxConnections(); + + Integer getConnectionBacklogLimit(); + + Long getStagingThreshold(); + + Integer getManagementPublishInterval(); + + String getVersion(); + + String getDataDirectory(); + + void addVirtualHost(VirtualHostConfig virtualHost); + + long getCreateTime(); + + void createBrokerConnection(String transport, + String host, + int port, + boolean durable, + String authMechanism, + String username, String password); + + String getFederationTag(); +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/BrokerConfigType.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/BrokerConfigType.java new file mode 100644 index 0000000000..82b2fc82d2 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/configuration/BrokerConfigType.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. + * + */ + +package org.apache.qpid.server.configuration; + +import java.util.*; +import java.io.File; + +public final class BrokerConfigType extends ConfigObjectType<BrokerConfigType, BrokerConfig> +{ + private static final List<BrokerProperty<?>> BROKER_PROPERTIES = new ArrayList<BrokerProperty<?>>(); + + public static interface BrokerProperty<S> extends ConfigProperty<BrokerConfigType, BrokerConfig, S> + { + } + + private abstract static class BrokerReadWriteProperty<S> extends ConfigProperty.ReadWriteConfigProperty<BrokerConfigType, BrokerConfig, S> implements BrokerProperty<S> + { + public BrokerReadWriteProperty(String name) + { + super(name); + BROKER_PROPERTIES.add(this); + } + } + + private abstract static class BrokerReadOnlyProperty<S> extends ConfigProperty.ReadOnlyConfigProperty<BrokerConfigType, BrokerConfig, S> implements BrokerProperty<S> + { + public BrokerReadOnlyProperty(String name) + { + super(name); + BROKER_PROPERTIES.add(this); + } + } + + public static final BrokerReadOnlyProperty<SystemConfig> SYSTEM_PROPERTY = new BrokerReadOnlyProperty<SystemConfig>("system") + { + public SystemConfig getValue(BrokerConfig object) + { + return object.getSystem(); + } + }; + + public static final BrokerReadOnlyProperty<Integer> PORT_PROPERTY = new BrokerReadOnlyProperty<Integer>("port") + { + public Integer getValue(BrokerConfig object) + { + return object.getPort(); + } + }; + + public static final BrokerReadOnlyProperty<Integer> WORKER_THREADS_PROPERTY = new BrokerReadOnlyProperty<Integer>("workerThreads") + { + public Integer getValue(BrokerConfig object) + { + return object.getWorkerThreads(); + } + }; + + public static final BrokerReadOnlyProperty<Integer> MAX_CONNECTIONS_PROPERTY = new BrokerReadOnlyProperty<Integer>("maxConnections") + { + public Integer getValue(BrokerConfig object) + { + return object.getMaxConnections(); + } + }; + + public static final BrokerReadOnlyProperty<Integer> CONNECTION_BACKLOG_LIMIT_PROPERTY = new BrokerReadOnlyProperty<Integer>("connectionBacklog") + { + public Integer getValue(BrokerConfig object) + { + return object.getConnectionBacklogLimit(); + } + }; + + public static final BrokerReadOnlyProperty<Long> STAGING_THRESHOLD_PROPERTY = new BrokerReadOnlyProperty<Long>("stagingThreshold") + { + public Long getValue(BrokerConfig object) + { + return object.getStagingThreshold(); + } + }; + + public static final BrokerReadOnlyProperty<Integer> MANAGEMENT_PUBLISH_INTERVAL_PROPERTY = new BrokerReadOnlyProperty<Integer>("mgmtPublishInterval") + { + public Integer getValue(BrokerConfig object) + { + return object.getManagementPublishInterval(); + } + }; + + public static final BrokerReadOnlyProperty<String> VERSION_PROPERTY = new BrokerReadOnlyProperty<String>("version") + { + public String getValue(BrokerConfig object) + { + return object.getVersion(); + } + }; + + public static final BrokerReadOnlyProperty<String> DATA_DIR_PROPERTY = new BrokerReadOnlyProperty<String>("dataDirectory") + { + public String getValue(BrokerConfig object) + { + return object.getDataDirectory(); + } + }; + + private static final BrokerConfigType INSTANCE = new BrokerConfigType(); + + private BrokerConfigType() + { + } + + public Collection<BrokerProperty<?>> getProperties() + { + return Collections.unmodifiableList(BROKER_PROPERTIES); + } + + public static BrokerConfigType getInstance() + { + return INSTANCE; + } + + + +}
\ No newline at end of file diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/ConfigObjectType.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/ConfigObjectType.java new file mode 100644 index 0000000000..c45aaaf1ee --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/configuration/ConfigObjectType.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. + * + */ + +package org.apache.qpid.server.configuration; + +import java.util.Collection; + +public abstract class ConfigObjectType<T extends ConfigObjectType<T,C>, C extends ConfiguredObject<T,C>> +{ + public abstract Collection<? extends ConfigProperty<T, C, ?>> getProperties(); + +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/ConfigProperty.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/ConfigProperty.java new file mode 100644 index 0000000000..2d88ba00a0 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/configuration/ConfigProperty.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. + * + */ + +package org.apache.qpid.server.configuration; + +public interface ConfigProperty<T extends ConfigObjectType<T,C>, C extends ConfiguredObject<T,C>, S> +{ + public String getName(); + + public S getValue(C object); + + public void setValue(C object, S value); + + public void clearValue(C object); + + public abstract static class ReadWriteConfigProperty<T extends ConfigObjectType<T,C>, C extends ConfiguredObject<T,C>,S> implements ConfigProperty<T, C, S> + { + private final String _name; + + protected ReadWriteConfigProperty(String name) + { + _name = name; + } + + public final String getName() + { + return _name; + } + } + + public abstract static class ReadOnlyConfigProperty<T extends ConfigObjectType<T,C>, C extends ConfiguredObject<T,C>, S> extends ReadWriteConfigProperty<T, C, S> + { + protected ReadOnlyConfigProperty(String name) + { + super(name); + } + + public final void setValue(C object, S value) + { + throw new UnsupportedOperationException("Cannot set value '"+getName()+"' as this property is read-only"); + } + + public final void clearValue(C object) + { + throw new UnsupportedOperationException("Cannot set value '"+getName()+"' as this property is read-only"); + } + } +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/ConfigStore.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/ConfigStore.java new file mode 100644 index 0000000000..572d886c18 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/configuration/ConfigStore.java @@ -0,0 +1,184 @@ +/* + * + * 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.configuration; + +import java.util.UUID; +import java.util.Collection; +import java.util.Collections; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.atomic.AtomicLong; + +public class ConfigStore +{ + private ConcurrentHashMap<ConfigObjectType, ConcurrentHashMap<UUID, ConfiguredObject>> _typeMap = + new ConcurrentHashMap<ConfigObjectType, ConcurrentHashMap<UUID, ConfiguredObject>>(); + + private ConcurrentHashMap<ConfigObjectType, CopyOnWriteArrayList<ConfigEventListener>> _listenerMap = + new ConcurrentHashMap<ConfigObjectType, CopyOnWriteArrayList<ConfigEventListener>>(); + + private SystemConfig _root; + + private final AtomicLong _objectIdSource = new AtomicLong(0l); + + + public enum Event + { + CREATED, DELETED; + } + + public interface ConfigEventListener<T extends ConfigObjectType<T,C>, C extends ConfiguredObject<T, C>> + { + void onEvent(C object, Event evt); + } + + private ConfigStore() + { + } + + public <T extends ConfigObjectType<T, C>, C extends ConfiguredObject<T, C>> ConfiguredObject<T, C> getConfiguredObject(ConfigObjectType<T,C> type, UUID id) + { + ConcurrentHashMap<UUID, ConfiguredObject> typeMap = _typeMap.get(type); + if(typeMap != null) + { + return typeMap.get(id); + } + else + { + return null; + } + + } + + public <T extends ConfigObjectType<T, C>, C extends ConfiguredObject<T, C>> Collection<? extends C> getConfiguredObjects(ConfigObjectType<T,C> type) + { + ConcurrentHashMap typeMap = _typeMap.get(type); + if(typeMap != null) + { + return typeMap.values(); + } + else + { + return Collections.EMPTY_LIST; + } + + } + + public <T extends ConfigObjectType<T, C>, C extends ConfiguredObject<T, C>> void addConfiguredObject(ConfiguredObject<T, C> object) + { + ConcurrentHashMap typeMap = _typeMap.get(object.getConfigType()); + if(typeMap == null) + { + typeMap = new ConcurrentHashMap(); + ConcurrentHashMap oldMap = _typeMap.putIfAbsent(object.getConfigType(), typeMap); + if(oldMap != null) + { + typeMap = oldMap; + } + + } + + typeMap.put(object.getId(), object); + sendEvent(Event.CREATED, object); + } + + + public <T extends ConfigObjectType<T, C>, C extends ConfiguredObject<T, C>> void removeConfiguredObject(ConfiguredObject<T, C> object) + { + ConcurrentHashMap typeMap = _typeMap.get(object.getConfigType()); + if(typeMap != null) + { + typeMap.remove(object.getId()); + sendEvent(Event.DELETED, object); + } + } + + public <T extends ConfigObjectType<T, C>, C extends ConfiguredObject<T, C>> void addConfigEventListener(T type, ConfigEventListener<T,C> listener) + { + CopyOnWriteArrayList listeners = _listenerMap.get(type); + if(listeners == null) + { + listeners = new CopyOnWriteArrayList(); + CopyOnWriteArrayList oldListeners = _listenerMap.putIfAbsent(type, listeners); + if(oldListeners != null) + { + listeners = oldListeners; + } + + } + + listeners.add(listener); + + } + + public <T extends ConfigObjectType<T, C>, C extends ConfiguredObject<T, C>> void removeConfigEventListener(T type, ConfigEventListener<T,C> listener) + { + CopyOnWriteArrayList listeners = _listenerMap.get(type); + if(listeners != null) + { + listeners.remove(listener); + } + } + + private void sendEvent(Event e, ConfiguredObject o) + { + CopyOnWriteArrayList<ConfigEventListener> listeners = _listenerMap.get(o.getConfigType()); + if(listeners != null) + { + for(ConfigEventListener listener : listeners) + { + listener.onEvent(o, e); + } + } + } + + public synchronized boolean setRoot(SystemConfig object) + { + if(_root == null) + { + _root = object; + addConfiguredObject(object); + return true; + } + else + { + return false; + } + } + + public UUID createId() + { + return new UUID(0l, _objectIdSource.getAndIncrement()); + } + + + public SystemConfig getRoot() + { + return _root; + } + + public static ConfigStore newInstance() + { + return new ConfigStore(); + } + +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/ConfiguredObject.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/ConfiguredObject.java new file mode 100644 index 0000000000..dd116ea29a --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/configuration/ConfiguredObject.java @@ -0,0 +1,36 @@ +/* + * + * 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.configuration; + +import java.util.UUID; + +public interface ConfiguredObject<T extends ConfigObjectType<T,C>, C extends ConfiguredObject<T, C>> +{ + public UUID getId(); + + public T getConfigType(); + + public ConfiguredObject getParent(); + + public boolean isDurable(); + +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/ConnectionConfig.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/ConnectionConfig.java new file mode 100644 index 0000000000..95fb7d39a1 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/configuration/ConnectionConfig.java @@ -0,0 +1,45 @@ +/* + * + * 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.configuration; + +public interface ConnectionConfig extends ConfiguredObject<ConnectionConfigType, ConnectionConfig> +{ + VirtualHostConfig getVirtualHost(); + + String getAddress(); + + Boolean isIncoming(); + + Boolean isSystemConnection(); + + Boolean isFederationLink(); + + String getAuthId(); + + String getRemoteProcessName(); + + Integer getRemotePID(); + + Integer getRemoteParentPID(); + + ConfigStore getConfigStore(); +}
\ No newline at end of file diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/ConnectionConfigType.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/ConnectionConfigType.java new file mode 100644 index 0000000000..9750b12dea --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/configuration/ConnectionConfigType.java @@ -0,0 +1,145 @@ +/* + * + * 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.configuration; + +import org.apache.qpid.server.exchange.ExchangeType; + +import java.util.*; + +public final class ConnectionConfigType extends ConfigObjectType<ConnectionConfigType, ConnectionConfig> +{ + private static final List<ConnectionProperty<?>> CONNECTION_PROPERTIES = new ArrayList<ConnectionProperty<?>>(); + + public static interface ConnectionProperty<S> extends ConfigProperty<ConnectionConfigType, ConnectionConfig, S> + { + } + + private abstract static class ConnectionReadWriteProperty<S> extends ConfigProperty.ReadWriteConfigProperty<ConnectionConfigType, ConnectionConfig, S> implements ConnectionProperty<S> + { + public ConnectionReadWriteProperty(String name) + { + super(name); + CONNECTION_PROPERTIES.add(this); + } + } + + private abstract static class ConnectionReadOnlyProperty<S> extends ConfigProperty.ReadOnlyConfigProperty<ConnectionConfigType, ConnectionConfig, S> implements ConnectionProperty<S> + { + public ConnectionReadOnlyProperty(String name) + { + super(name); + CONNECTION_PROPERTIES.add(this); + } + } + + public static final ConnectionReadOnlyProperty<VirtualHostConfig> VIRTUAL_HOST_PROPERTY = new ConnectionReadOnlyProperty<VirtualHostConfig>("virtualHost") + { + public VirtualHostConfig getValue(ConnectionConfig object) + { + return object.getVirtualHost(); + } + }; + + public static final ConnectionReadOnlyProperty<String> ADDRESS_PROPERTY = new ConnectionReadOnlyProperty<String>("address") + { + public String getValue(ConnectionConfig object) + { + return object.getAddress(); + } + }; + + public static final ConnectionReadOnlyProperty<Boolean> INCOMING_PROPERTY = new ConnectionReadOnlyProperty<Boolean>("incoming") + { + public Boolean getValue(ConnectionConfig object) + { + return object.isIncoming(); + } + }; + + public static final ConnectionReadOnlyProperty<Boolean> SYSTEM_CONNECTION_PROPERTY = new ConnectionReadOnlyProperty<Boolean>("systemConnection") + { + public Boolean getValue(ConnectionConfig object) + { + return object.isSystemConnection(); + } + }; + + public static final ConnectionReadOnlyProperty<Boolean> FEDERATION_LINK_PROPERTY = new ConnectionReadOnlyProperty<Boolean>("federationLink") + { + public Boolean getValue(ConnectionConfig object) + { + return object.isFederationLink(); + } + }; + + public static final ConnectionReadOnlyProperty<String> AUTH_ID_PROPERTY = new ConnectionReadOnlyProperty<String>("authId") + { + public String getValue(ConnectionConfig object) + { + return object.getAuthId(); + } + }; + + public static final ConnectionReadOnlyProperty<String> REMOTE_PROCESS_NAME_PROPERTY = new ConnectionReadOnlyProperty<String>("remoteProcessName") + { + public String getValue(ConnectionConfig object) + { + return object.getRemoteProcessName(); + } + }; + + + public static final ConnectionReadOnlyProperty<Integer> REMOTE_PID_PROPERTY = new ConnectionReadOnlyProperty<Integer>("remotePid") + { + public Integer getValue(ConnectionConfig object) + { + return object.getRemotePID(); + } + }; + + public static final ConnectionReadOnlyProperty<Integer> REMOTE_PARENT_PID_PROPERTY = new ConnectionReadOnlyProperty<Integer>("remoteParentPid") + { + public Integer getValue(ConnectionConfig object) + { + return object.getRemoteParentPID(); + } + }; + + private static final ConnectionConfigType INSTANCE = new ConnectionConfigType(); + + private ConnectionConfigType() + { + } + + public Collection<ConnectionProperty<?>> getProperties() + { + return Collections.unmodifiableList(CONNECTION_PROPERTIES); + } + + public static ConnectionConfigType getInstance() + { + return INSTANCE; + } + + + +}
\ No newline at end of file diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/ExchangeConfig.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/ExchangeConfig.java new file mode 100644 index 0000000000..40dc88c28c --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/configuration/ExchangeConfig.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.server.configuration; + +import org.apache.qpid.server.exchange.ExchangeType; + +import java.util.Map; + + +public interface ExchangeConfig extends ConfiguredObject<ExchangeConfigType, ExchangeConfig> +{ + VirtualHostConfig getVirtualHost(); + + String getName(); + + ExchangeType getType(); + + boolean isAutoDelete(); + + ExchangeConfig getAlternateExchange(); + + Map<String, Object> getArguments(); + + + long getBindingCount(); + + long getBindingCountHigh(); + + long getMsgReceives(); + + long getMsgRoutes(); + + long getByteReceives(); + + long getByteRoutes(); + + long getCreateTime(); +}
\ No newline at end of file diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/ExchangeConfigType.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/ExchangeConfigType.java new file mode 100644 index 0000000000..2095301ad6 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/configuration/ExchangeConfigType.java @@ -0,0 +1,113 @@ +/* + * + * 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.configuration; + +import org.apache.qpid.server.exchange.ExchangeType; + +import java.util.*; + +public final class ExchangeConfigType extends ConfigObjectType<ExchangeConfigType, ExchangeConfig> +{ + private static final List<ExchangeProperty<?>> EXCHANGE_PROPERTIES = new ArrayList<ExchangeProperty<?>>(); + + public static interface ExchangeProperty<S> extends ConfigProperty<ExchangeConfigType, ExchangeConfig, S> + { + } + + private abstract static class ExchangeReadWriteProperty<S> extends ConfigProperty.ReadWriteConfigProperty<ExchangeConfigType, ExchangeConfig, S> implements ExchangeProperty<S> + { + public ExchangeReadWriteProperty(String name) + { + super(name); + EXCHANGE_PROPERTIES.add(this); + } + } + + private abstract static class ExchangeReadOnlyProperty<S> extends ConfigProperty.ReadOnlyConfigProperty<ExchangeConfigType, ExchangeConfig, S> implements ExchangeProperty<S> + { + public ExchangeReadOnlyProperty(String name) + { + super(name); + EXCHANGE_PROPERTIES.add(this); + } + } + + public static final ExchangeReadOnlyProperty<VirtualHostConfig> VIRTUAL_HOST_PROPERTY = new ExchangeReadOnlyProperty<VirtualHostConfig>("virtualHost") + { + public VirtualHostConfig getValue(ExchangeConfig object) + { + return object.getVirtualHost(); + } + }; + + public static final ExchangeReadOnlyProperty<String> NAME_PROPERTY = new ExchangeReadOnlyProperty<String>("name") + { + public String getValue(ExchangeConfig object) + { + return object.getName(); + } + }; + + public static final ExchangeReadOnlyProperty<Boolean> AUTODELETE_PROPERTY = new ExchangeReadOnlyProperty<Boolean>("autodelete") + { + public Boolean getValue(ExchangeConfig object) + { + return object.isAutoDelete(); + } + }; + + + public static final ExchangeReadOnlyProperty<ExchangeConfig> ALTERNATE_EXCHANGE_PROPERTY = new ExchangeReadOnlyProperty<ExchangeConfig>("alternateExchange") + { + public ExchangeConfig getValue(ExchangeConfig object) + { + return object.getAlternateExchange(); + } + }; + + public static final ExchangeReadOnlyProperty<Map<String,Object>> ARGUMENTS = new ExchangeReadOnlyProperty<Map<String,Object>>("arguments") + { + public Map<String,Object> getValue(ExchangeConfig object) + { + return object.getArguments(); + } + }; + + private static final ExchangeConfigType INSTANCE = new ExchangeConfigType(); + + private ExchangeConfigType() + { + } + + public Collection<ExchangeProperty<?>> getProperties() + { + return Collections.unmodifiableList(EXCHANGE_PROPERTIES); + } + + public static ExchangeConfigType getInstance() + { + return INSTANCE; + } + + + +}
\ No newline at end of file diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/LinkConfig.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/LinkConfig.java new file mode 100644 index 0000000000..82e0647917 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/configuration/LinkConfig.java @@ -0,0 +1,59 @@ +/* + * + * 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.configuration; + +import org.apache.qpid.server.exchange.ExchangeType; + +import java.util.Map; + + +public interface LinkConfig extends ConfiguredObject<LinkConfigType, LinkConfig> +{ + VirtualHostConfig getVirtualHost(); + + + String getTransport(); + + String getHost(); + + int getPort(); + + String getRemoteVhost(); + + String getAuthMechanism(); + + String getUsername(); + + String getPassword(); + + void close(); + + long getCreateTime(); + + void createBridge(boolean durable, + boolean dynamic, + boolean srcIsQueue, + boolean srcIsLocal, + String src, + String dest, + String key, String tag, String excludes); +}
\ No newline at end of file diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/LinkConfigType.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/LinkConfigType.java new file mode 100644 index 0000000000..4dc46b70c9 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/configuration/LinkConfigType.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.server.configuration; + +import org.apache.qpid.server.exchange.ExchangeType; + +import java.util.*; + +public final class LinkConfigType extends ConfigObjectType<LinkConfigType, LinkConfig> +{ + private static final List<LinkProperty<?>> LINK_PROPERTIES = new ArrayList<LinkProperty<?>>(); + + public static interface LinkProperty<S> extends ConfigProperty<LinkConfigType, LinkConfig, S> + { + } + + private abstract static class LinkReadWriteProperty<S> extends ConfigProperty.ReadWriteConfigProperty<LinkConfigType, LinkConfig, S> implements LinkProperty<S> + { + public LinkReadWriteProperty(String name) + { + super(name); + LINK_PROPERTIES.add(this); + } + } + + private abstract static class LinkReadOnlyProperty<S> extends ConfigProperty.ReadOnlyConfigProperty<LinkConfigType, LinkConfig, S> implements LinkProperty<S> + { + public LinkReadOnlyProperty(String name) + { + super(name); + LINK_PROPERTIES.add(this); + } + } + + public static final LinkReadOnlyProperty<VirtualHostConfig> VIRTUAL_HOST_PROPERTY = new LinkReadOnlyProperty<VirtualHostConfig>("virtualHost") + { + public VirtualHostConfig getValue(LinkConfig object) + { + return object.getVirtualHost(); + } + }; + + public static final LinkReadOnlyProperty<String> TRANSPORT_PROPERTY = new LinkReadOnlyProperty<String>("transport") + { + public String getValue(LinkConfig object) + { + return object.getTransport(); + } + }; + + public static final LinkReadOnlyProperty<String> HOST_PROPERTY = new LinkReadOnlyProperty<String>("host") + { + public String getValue(LinkConfig object) + { + return object.getHost(); + } + }; + + public static final LinkReadOnlyProperty<Integer> PORT_PROPERTY = new LinkReadOnlyProperty<Integer>("host") + { + public Integer getValue(LinkConfig object) + { + return object.getPort(); + } + }; + + public static final LinkReadOnlyProperty<String> REMOTE_VHOST_PROPERTY = new LinkReadOnlyProperty<String>("remoteVhost") + { + public String getValue(LinkConfig object) + { + return object.getRemoteVhost(); + } + }; + + public static final LinkReadOnlyProperty<String> AUTH_MECHANISM_PROPERTY = new LinkReadOnlyProperty<String>("authMechanism") + { + public String getValue(LinkConfig object) + { + return object.getAuthMechanism(); + } + }; + + public static final LinkReadOnlyProperty<String> USERNAME_PROPERTY = new LinkReadOnlyProperty<String>("username") + { + public String getValue(LinkConfig object) + { + return object.getUsername(); + } + }; + + public static final LinkReadOnlyProperty<String> PASSWORD_PROPERTY = new LinkReadOnlyProperty<String>("password") + { + public String getValue(LinkConfig object) + { + return object.getPassword(); + } + }; + + private static final LinkConfigType INSTANCE = new LinkConfigType(); + + private LinkConfigType() + { + } + + public Collection<LinkProperty<?>> getProperties() + { + return Collections.unmodifiableList(LINK_PROPERTIES); + } + + public static LinkConfigType getInstance() + { + return INSTANCE; + } + + + +}
\ No newline at end of file diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/QueueConfig.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/QueueConfig.java new file mode 100644 index 0000000000..a451091fee --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/configuration/QueueConfig.java @@ -0,0 +1,72 @@ +/* + * + * 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.configuration; + +import java.util.Map; + + +public interface QueueConfig extends ConfiguredObject<QueueConfigType, QueueConfig> +{ + VirtualHostConfig getVirtualHost(); + + String getName(); + + boolean isExclusive(); + + boolean isAutoDelete(); + + ExchangeConfig getAlternateExchange(); + + Map<String, Object> getArguments(); + + long getReceivedMessageCount(); + + int getMessageCount(); + + long getQueueDepth(); + + int getConsumerCount(); + + int getBindingCount(); + + ConfigStore getConfigStore(); + + long getMessageDequeueCount(); + + long getTotalEnqueueSize(); + + long getTotalDequeueSize(); + + int getBindingCountHigh(); + + long getPersistentByteEnqueues(); + + long getPersistentByteDequeues(); + + long getPersistentMsgEnqueues(); + + long getPersistentMsgDequeues(); + + void purge(long request); + + long getCreateTime(); +}
\ No newline at end of file diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/QueueConfigType.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/QueueConfigType.java new file mode 100644 index 0000000000..a794ed9747 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/configuration/QueueConfigType.java @@ -0,0 +1,121 @@ +/* + * + * 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.configuration; + +import org.apache.qpid.server.exchange.ExchangeType; + +import java.util.*; + +public final class QueueConfigType extends ConfigObjectType<QueueConfigType, QueueConfig> +{ + private static final List<QueueProperty<?>> QUEUE_PROPERTIES = new ArrayList<QueueProperty<?>>(); + + public static interface QueueProperty<S> extends ConfigProperty<QueueConfigType, QueueConfig, S> + { + } + + private abstract static class QueueReadWriteProperty<S> extends ConfigProperty.ReadWriteConfigProperty<QueueConfigType, QueueConfig, S> implements QueueProperty<S> + { + public QueueReadWriteProperty(String name) + { + super(name); + QUEUE_PROPERTIES.add(this); + } + } + + private abstract static class QueueReadOnlyProperty<S> extends ConfigProperty.ReadOnlyConfigProperty<QueueConfigType, QueueConfig, S> implements QueueProperty<S> + { + public QueueReadOnlyProperty(String name) + { + super(name); + QUEUE_PROPERTIES.add(this); + } + } + + public static final QueueReadOnlyProperty<VirtualHostConfig> VISTUAL_HOST_PROPERTY = new QueueReadOnlyProperty<VirtualHostConfig>("virtualHost") + { + public VirtualHostConfig getValue(QueueConfig object) + { + return object.getVirtualHost(); + } + }; + + public static final QueueReadOnlyProperty<String> NAME_PROPERTY = new QueueReadOnlyProperty<String>("name") + { + public String getValue(QueueConfig object) + { + return object.getName(); + } + }; + + public static final QueueReadOnlyProperty<Boolean> AUTODELETE_PROPERTY = new QueueReadOnlyProperty<Boolean>("autodelete") + { + public Boolean getValue(QueueConfig object) + { + return object.isAutoDelete(); + } + }; + + public static final QueueReadOnlyProperty<Boolean> EXCLUSIVE_PROPERTY = new QueueReadOnlyProperty<Boolean>("exclusive") + { + public Boolean getValue(QueueConfig object) + { + return object.isExclusive(); + } + }; + + public static final QueueReadOnlyProperty<ExchangeConfig> ALTERNATE_EXCHANGE_PROPERTY = new QueueReadOnlyProperty<ExchangeConfig>("alternateExchange") + { + public ExchangeConfig getValue(QueueConfig object) + { + return object.getAlternateExchange(); + } + }; + + public static final QueueReadOnlyProperty<Map<String,Object>> ARGUMENTS = new QueueReadOnlyProperty<Map<String,Object>>("arguments") + { + public Map<String,Object> getValue(QueueConfig object) + { + return object.getArguments(); + } + }; + + + private static final QueueConfigType INSTANCE = new QueueConfigType(); + + private QueueConfigType() + { + } + + public Collection<QueueProperty<?>> getProperties() + { + return Collections.unmodifiableList(QUEUE_PROPERTIES); + } + + public static QueueConfigType getInstance() + { + return INSTANCE; + } + + + +}
\ No newline at end of file diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/QueueConfiguration.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/QueueConfiguration.java index 5c73e353de..44759bb4b8 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/configuration/QueueConfiguration.java +++ b/java/broker/src/main/java/org/apache/qpid/server/configuration/QueueConfiguration.java @@ -118,4 +118,13 @@ public class QueueConfiguration return _config.getLong("flowResumeCapacity", _vHostConfig.getFlowResumeCapacity()); } + public boolean isLVQ() + { + return _config.getBoolean("lvq", false); + } + + public String getLVQKey() + { + return _config.getString("lvqKey", null); + } } diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/SessionConfig.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/SessionConfig.java new file mode 100644 index 0000000000..ae01ab25ea --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/configuration/SessionConfig.java @@ -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.configuration; + +public interface SessionConfig extends ConfiguredObject<SessionConfigType, SessionConfig> +{ + VirtualHostConfig getVirtualHost(); + + String getSessionName(); + + int getChannel(); + + ConnectionConfig getConnectionConfig(); + + boolean isAttached(); + + long getDetachedLifespan(); + + Long getExpiryTime(); + + Long getMaxClientRate(); +}
\ No newline at end of file diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/SessionConfigType.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/SessionConfigType.java new file mode 100644 index 0000000000..97cf275575 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/configuration/SessionConfigType.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.server.configuration; + +import org.apache.qpid.server.exchange.ExchangeType; + +import java.util.*; + +public final class SessionConfigType extends ConfigObjectType<SessionConfigType, SessionConfig> +{ + private static final List<SessionProperty<?>> SESSION_PROPERTIES = new ArrayList<SessionProperty<?>>(); + + public static interface SessionProperty<S> extends ConfigProperty<SessionConfigType, SessionConfig, S> + { + } + + private abstract static class SessionReadWriteProperty<S> extends ConfigProperty.ReadWriteConfigProperty<SessionConfigType, SessionConfig, S> implements SessionProperty<S> + { + public SessionReadWriteProperty(String name) + { + super(name); + SESSION_PROPERTIES.add(this); + } + } + + private abstract static class SessionReadOnlyProperty<S> extends ConfigProperty.ReadOnlyConfigProperty<SessionConfigType, SessionConfig, S> implements SessionProperty<S> + { + public SessionReadOnlyProperty(String name) + { + super(name); + SESSION_PROPERTIES.add(this); + } + } + + public static final SessionReadOnlyProperty<VirtualHostConfig> VIRTUAL_HOST_PROPERTY = new SessionReadOnlyProperty<VirtualHostConfig>("virtualHost") + { + public VirtualHostConfig getValue(SessionConfig object) + { + return object.getVirtualHost(); + } + }; + + public static final SessionReadOnlyProperty<String> NAME_PROPERTY = new SessionReadOnlyProperty<String>("name") + { + public String getValue(SessionConfig object) + { + return object.getSessionName(); + } + }; + + public static final SessionReadOnlyProperty<Integer> CHANNEL_ID_PROPERTY = new SessionReadOnlyProperty<Integer>("channelId") + { + public Integer getValue(SessionConfig object) + { + return object.getChannel(); + } + }; + + public static final SessionReadOnlyProperty<ConnectionConfig> CONNECTION_PROPERTY = new SessionReadOnlyProperty<ConnectionConfig>("connection") + { + public ConnectionConfig getValue(SessionConfig object) + { + return object.getConnectionConfig(); + } + }; + + public static final SessionReadOnlyProperty<Boolean> ATTACHED_PROPERTY = new SessionReadOnlyProperty<Boolean>("attached") + { + public Boolean getValue(SessionConfig object) + { + return object.isAttached(); + } + }; + + public static final SessionReadOnlyProperty<Long> DETACHED_LIFESPAN_PROPERTY = new SessionReadOnlyProperty<Long>("detachedLifespan") + { + public Long getValue(SessionConfig object) + { + return object.getDetachedLifespan(); + } + }; + + public static final SessionReadOnlyProperty<Long> EXPIRE_TIME_PROPERTY = new SessionReadOnlyProperty<Long>("expireTime") + { + public Long getValue(SessionConfig object) + { + return object.getExpiryTime(); + } + }; + + public static final SessionReadOnlyProperty<Long> MAX_CLIENT_RATE_PROPERTY = new SessionReadOnlyProperty<Long>("maxClientRate") + { + public Long getValue(SessionConfig object) + { + return object.getMaxClientRate(); + } + }; + + private static final SessionConfigType INSTANCE = new SessionConfigType(); + + private SessionConfigType() + { + } + + public Collection<SessionProperty<?>> getProperties() + { + return Collections.unmodifiableList(SESSION_PROPERTIES); + } + + public static SessionConfigType getInstance() + { + return INSTANCE; + } + + + +}
\ No newline at end of file diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/SubscriptionConfig.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/SubscriptionConfig.java new file mode 100644 index 0000000000..985ecb2be9 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/configuration/SubscriptionConfig.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.server.configuration; + +import java.util.Map; + + +public interface SubscriptionConfig extends ConfiguredObject<SubscriptionConfigType, SubscriptionConfig> +{ + + SessionConfig getSessionConfig(); + + QueueConfig getQueue(); + + String getName(); + + Map<String, Object> getArguments(); + + String getCreditMode(); + + boolean isBrowsing(); + + boolean isExclusive(); + + boolean isExplicitAcknowledge(); + + +}
\ No newline at end of file diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/SubscriptionConfigType.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/SubscriptionConfigType.java new file mode 100644 index 0000000000..99d3273b55 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/configuration/SubscriptionConfigType.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.server.configuration; + + +import java.util.*; + +public final class SubscriptionConfigType extends ConfigObjectType<SubscriptionConfigType, SubscriptionConfig> +{ + private static final List<SubscriptionProperty<?>> SUBSCRIPTION_PROPERTIES = new ArrayList<SubscriptionProperty<?>>(); + + public static interface SubscriptionProperty<S> extends ConfigProperty<SubscriptionConfigType, SubscriptionConfig, S> + { + } + + private abstract static class SubscriptionReadWriteProperty<S> extends ConfigProperty.ReadWriteConfigProperty<SubscriptionConfigType, SubscriptionConfig, S> implements SubscriptionProperty<S> + { + public SubscriptionReadWriteProperty(String name) + { + super(name); + SUBSCRIPTION_PROPERTIES.add(this); + } + } + + private abstract static class SubscriptionReadOnlyProperty<S> extends ConfigProperty.ReadOnlyConfigProperty<SubscriptionConfigType, SubscriptionConfig, S> implements SubscriptionProperty<S> + { + public SubscriptionReadOnlyProperty(String name) + { + super(name); + SUBSCRIPTION_PROPERTIES.add(this); + } + } + + public static final SubscriptionReadOnlyProperty<SessionConfig> SESSION_PROPERTY = new SubscriptionReadOnlyProperty<SessionConfig>("session") + { + public SessionConfig getValue(SubscriptionConfig object) + { + return object.getSessionConfig(); + } + }; + + public static final SubscriptionReadOnlyProperty<QueueConfig> QUEUE_PROPERTY = new SubscriptionReadOnlyProperty<QueueConfig>("queue") + { + public QueueConfig getValue(SubscriptionConfig object) + { + return object.getQueue(); + } + }; + + public static final SubscriptionReadOnlyProperty<String> NAME_PROPERTY = new SubscriptionReadOnlyProperty<String>("name") + { + public String getValue(SubscriptionConfig object) + { + return object.getName(); + } + }; + + public static final SubscriptionReadOnlyProperty<Map<String,Object>> ARGUMENTS = new SubscriptionReadOnlyProperty<Map<String,Object>>("arguments") + { + public Map<String,Object> getValue(SubscriptionConfig object) + { + return object.getArguments(); + } + }; + + public static final SubscriptionReadOnlyProperty<String> CREDIT_MODE_PROPERTY = new SubscriptionReadOnlyProperty<String>("creditMode") + { + public String getValue(SubscriptionConfig object) + { + return object.getCreditMode(); + } + }; + + public static final SubscriptionReadOnlyProperty<Boolean> BROWSING_PROPERTY = new SubscriptionReadOnlyProperty<Boolean>("browsing") + { + public Boolean getValue(SubscriptionConfig object) + { + return object.isBrowsing(); + } + }; + + public static final SubscriptionReadOnlyProperty<Boolean> EXCLUSIVE_PROPERTY = new SubscriptionReadOnlyProperty<Boolean>("exclusive") + { + public Boolean getValue(SubscriptionConfig object) + { + return object.isExclusive(); + } + }; + + public static final SubscriptionReadOnlyProperty<Boolean> EXPLICIT_ACK_PROPERTY = new SubscriptionReadOnlyProperty<Boolean>("explicitAck") + { + public Boolean getValue(SubscriptionConfig object) + { + return object.isExplicitAcknowledge(); + } + }; + + private static final SubscriptionConfigType INSTANCE = new SubscriptionConfigType(); + + private SubscriptionConfigType() + { + } + + public Collection<SubscriptionProperty<?>> getProperties() + { + return Collections.unmodifiableList(SUBSCRIPTION_PROPERTIES); + } + + + public static SubscriptionConfigType getInstance() + { + return INSTANCE; + } + + + +}
\ No newline at end of file diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/SystemConfig.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/SystemConfig.java new file mode 100644 index 0000000000..1e722ea191 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/configuration/SystemConfig.java @@ -0,0 +1,44 @@ +/* + * + * 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.configuration; + +public interface SystemConfig extends ConfiguredObject<SystemConfigType,SystemConfig> +{ + String getName(); + + String getOperatingSystemName(); + + String getNodeName(); + + + String getOSRelease(); + + String getOSVersion(); + + String getOSArchitecture(); + + void addBroker(BrokerConfig broker); + + void removeBroker(BrokerConfig broker); + + long getCreateTime(); +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/SystemConfigImpl.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/SystemConfigImpl.java new file mode 100644 index 0000000000..09ebb07105 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/configuration/SystemConfigImpl.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.server.configuration; + +import java.util.UUID; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.net.InetAddress; +import java.net.UnknownHostException; + +public class SystemConfigImpl implements SystemConfig +{ + private static final String OS_NAME = System.getProperty("os.name"); + private static final String OS_ARCH = System.getProperty("os.arch"); + private static final String OS_VERSION = System.getProperty("os.version"); + + private final UUID _id; + private String _name; + + private final String _host; + + private final Map<UUID, BrokerConfig> _brokers = new ConcurrentHashMap<UUID, BrokerConfig>(); + + private final long _createTime = System.currentTimeMillis(); + private final ConfigStore _store; + + public SystemConfigImpl(ConfigStore store) + { + this(store.createId(), store); + } + + public SystemConfigImpl(UUID id, ConfigStore store) + { + _id = id; + _store = store; + String host; + try + { + InetAddress addr = InetAddress.getLocalHost(); + host = addr.getHostName(); + } + catch (UnknownHostException e) + { + host="localhost"; + } + _host = host; + } + + public String getName() + { + return _name; + } + + public String getOperatingSystemName() + { + return OS_NAME; + } + + public String getNodeName() + { + return _host; + } + + public String getOSRelease() + { + return OS_VERSION; + } + + public String getOSVersion() + { + return ""; + } + + public String getOSArchitecture() + { + return OS_ARCH; + } + + public UUID getId() + { + return _id; + } + + public SystemConfigType getConfigType() + { + return SystemConfigType.getInstance(); + } + + public ConfiguredObject getParent() + { + return null; + } + + public boolean isDurable() + { + return false; + } + + public void addBroker(final BrokerConfig broker) + { + broker.setSystem(this); + _store.addConfiguredObject(broker); + _brokers.put(broker.getId(), broker); + } + + public void removeBroker(final BrokerConfig broker) + { + _brokers.remove(broker.getId()); + _store.removeConfiguredObject(broker); + } + + public long getCreateTime() + { + return _createTime; + } + +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/SystemConfigType.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/SystemConfigType.java new file mode 100644 index 0000000000..f5aabd2345 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/configuration/SystemConfigType.java @@ -0,0 +1,128 @@ +/* + * + * 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.configuration; + +import java.util.*; + +public final class SystemConfigType extends ConfigObjectType<SystemConfigType, SystemConfig> +{ + private static final List<SystemProperty<?>> SYSTEM_PROPERTIES = new ArrayList<SystemProperty<?>>(); + + public static interface SystemProperty<S> extends ConfigProperty<SystemConfigType, SystemConfig, S> + { + } + + private abstract static class SystemReadWriteProperty<S> extends ConfigProperty.ReadWriteConfigProperty<SystemConfigType, SystemConfig, S> implements SystemProperty<S> + { + public SystemReadWriteProperty(String name) + { + super(name); + SYSTEM_PROPERTIES.add(this); + } + } + + private abstract static class SystemReadOnlyProperty<S> extends ConfigProperty.ReadOnlyConfigProperty<SystemConfigType, SystemConfig, S> implements SystemProperty<S> + { + public SystemReadOnlyProperty(String name) + { + super(name); + SYSTEM_PROPERTIES.add(this); + } + } + + public static final SystemReadOnlyProperty<String> NAME_PROPERTY = new SystemReadOnlyProperty<String>("name") + { + public String getValue(SystemConfig object) + { + return object.getName(); + } + }; + + public static final SystemReadOnlyProperty<UUID> ID_PROPERTY = new SystemReadOnlyProperty<UUID>("id") + { + public UUID getValue(SystemConfig object) + { + return object.getId(); + } + }; + + public static final SystemReadOnlyProperty<String> OS_NAME_PROPERTY = new SystemReadOnlyProperty<String>("osName") + { + public String getValue(SystemConfig object) + { + return object.getOperatingSystemName(); + } + }; + + public static final SystemReadOnlyProperty<String> NODE_NAME_PROPERTY = new SystemReadOnlyProperty<String>("nodeName") + { + public String getValue(SystemConfig object) + { + return object.getNodeName(); + } + }; + + public static final SystemReadOnlyProperty<String> RELEASE_PROPERTY = new SystemReadOnlyProperty<String>("release") + { + public String getValue(SystemConfig object) + { + return object.getOSRelease(); + } + }; + + public static final SystemReadOnlyProperty<String> VERSION_PROPERTY = new SystemReadOnlyProperty<String>("version") + { + public String getValue(SystemConfig object) + { + return object.getOSVersion(); + } + }; + + public static final SystemReadOnlyProperty<String> MACHINE_PROPERTY = new SystemReadOnlyProperty<String>("machine") + { + public String getValue(SystemConfig object) + { + return object.getOSArchitecture(); + } + }; + + private static final SystemConfigType INSTANCE = new SystemConfigType(); + + private SystemConfigType() + { + } + + public Collection<SystemProperty<?>> getProperties() + { + return Collections.unmodifiableList(SYSTEM_PROPERTIES); + } + + + + public static SystemConfigType getInstance() + { + return INSTANCE; + } + + + +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/VirtualHostConfig.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/VirtualHostConfig.java new file mode 100644 index 0000000000..9431e5175f --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/configuration/VirtualHostConfig.java @@ -0,0 +1,36 @@ +/* + * + * 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.configuration; + +public interface VirtualHostConfig extends ConfiguredObject<VirtualHostConfigType, VirtualHostConfig> +{ + String getName(); + + BrokerConfig getBroker(); + + String getFederationTag(); + + void setBroker(BrokerConfig brokerConfig); + + long getCreateTime(); + +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/VirtualHostConfigType.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/VirtualHostConfigType.java new file mode 100644 index 0000000000..96682335bf --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/configuration/VirtualHostConfigType.java @@ -0,0 +1,96 @@ +/* + * + * 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.configuration; + +import java.util.*; + +public class VirtualHostConfigType extends ConfigObjectType<VirtualHostConfigType, VirtualHostConfig> +{ + private static final List<VirtualHostProperty<?>> VIRTUAL_HOST_PROPERTIES = new ArrayList<VirtualHostProperty<?>>(); + private static final VirtualHostConfigType INSTANCE = new VirtualHostConfigType(); +public static interface VirtualHostProperty<S> extends ConfigProperty<VirtualHostConfigType, VirtualHostConfig, S> + { + } + + private abstract static class VirtualHostReadWriteProperty<S> extends ConfigProperty.ReadWriteConfigProperty<VirtualHostConfigType, VirtualHostConfig, S> implements VirtualHostProperty<S> + { + public VirtualHostReadWriteProperty(String name) + { + super(name); + VIRTUAL_HOST_PROPERTIES.add(this); + } + } + + private abstract static class VirtualHostReadOnlyProperty<S> extends ConfigProperty.ReadOnlyConfigProperty<VirtualHostConfigType, VirtualHostConfig, S> implements VirtualHostProperty<S> + { + public VirtualHostReadOnlyProperty(String name) + { + super(name); + VIRTUAL_HOST_PROPERTIES.add(this); + } + } + + + public static final VirtualHostReadOnlyProperty<String> NAME_PROPERTY = new VirtualHostReadOnlyProperty<String>("name") + { + public String getValue(VirtualHostConfig object) + { + return object.getName(); + } + }; + + + public static final VirtualHostReadOnlyProperty<BrokerConfig> BROKER_PROPERTY = new VirtualHostReadOnlyProperty<BrokerConfig>("broker") + { + public BrokerConfig getValue(VirtualHostConfig object) + { + return object.getBroker(); + } + }; + + public static final VirtualHostReadOnlyProperty<String> FEDERATION_TAG_PROPERTY = new VirtualHostReadOnlyProperty<String>("federationTag") + { + public String getValue(VirtualHostConfig object) + { + return object.getFederationTag(); + } + }; + + + + public Collection<? extends ConfigProperty<VirtualHostConfigType, VirtualHostConfig, ?>> getProperties() + { + return Collections.unmodifiableList(VIRTUAL_HOST_PROPERTIES); + } + + + private VirtualHostConfigType() + { + } + + public static VirtualHostConfigType getInstance() + { + return INSTANCE; + } + + +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/exchange/AbstractExchange.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/AbstractExchange.java index 07f33b4a8f..32b95ff742 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/exchange/AbstractExchange.java +++ b/java/broker/src/main/java/org/apache/qpid/server/exchange/AbstractExchange.java @@ -20,51 +20,57 @@ */ package org.apache.qpid.server.exchange; -import javax.management.MalformedObjectNameException; -import javax.management.NotCompliantMBeanException; -import javax.management.ObjectName; -import javax.management.JMException; -import javax.management.openmbean.OpenType; -import javax.management.openmbean.CompositeType; -import javax.management.openmbean.TabularType; -import javax.management.openmbean.TabularDataSupport; -import javax.management.openmbean.OpenDataException; -import javax.management.openmbean.SimpleType; -import javax.management.openmbean.ArrayType; +import org.apache.log4j.Logger; import org.apache.qpid.AMQException; import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.management.common.mbeans.ManagedExchange; -import org.apache.qpid.server.management.AMQManagedObject; +import org.apache.qpid.server.binding.Binding; +import org.apache.qpid.server.configuration.ConfigStore; +import org.apache.qpid.server.configuration.ConfiguredObject; +import org.apache.qpid.server.configuration.ExchangeConfigType; +import org.apache.qpid.server.logging.LogSubject; +import org.apache.qpid.server.logging.actors.CurrentActor; +import org.apache.qpid.server.logging.messages.ExchangeMessages; +import org.apache.qpid.server.logging.subjects.ExchangeLogSubject; import org.apache.qpid.server.management.Managable; import org.apache.qpid.server.management.ManagedObject; -import org.apache.qpid.server.management.ManagedObjectRegistry; -import org.apache.qpid.server.queue.QueueRegistry; +import org.apache.qpid.server.message.InboundMessage; import org.apache.qpid.server.queue.AMQQueue; -import org.apache.qpid.server.registry.ApplicationRegistry; +import org.apache.qpid.server.queue.BaseQueue; +import org.apache.qpid.server.queue.QueueRegistry; import org.apache.qpid.server.virtualhost.VirtualHost; -import org.apache.qpid.server.logging.actors.CurrentActor; -import org.apache.qpid.server.logging.messages.ExchangeMessages; -import org.apache.qpid.server.logging.subjects.ExchangeLogSubject; -import org.apache.qpid.server.logging.LogSubject; -import org.apache.log4j.Logger; +import javax.management.JMException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; import java.util.Map; +import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicLong; public abstract class AbstractExchange implements Exchange, Managable { + + private AMQShortString _name; + private final AtomicBoolean _closed = new AtomicBoolean(); private Exchange _alternateExchange; protected boolean _durable; - protected String _exchangeType; protected int _ticket; private VirtualHost _virtualHost; - protected ExchangeMBean _exchangeMbean; + private final List<Exchange.Task> _closeTaskList = new CopyOnWriteArrayList<Exchange.Task>(); + + + protected AbstractExchangeMBean _exchangeMbean; /** * Whether the exchange is automatically deleted once all queues have detached from it @@ -75,95 +81,49 @@ public abstract class AbstractExchange implements Exchange, Managable private LogSubject _logSubject; private Map<ExchangeReferrer,Object> _referrers = new ConcurrentHashMap<ExchangeReferrer,Object>(); - /** - * Abstract MBean class. This has some of the methods implemented from - * management intrerface for exchanges. Any implementaion of an - * Exchange MBean should extend this class. - */ - protected abstract class ExchangeMBean extends AMQManagedObject implements ManagedExchange - { - // open mbean data types for representing exchange bindings - protected OpenType[] _bindingItemTypes; - protected CompositeType _bindingDataType; - protected TabularType _bindinglistDataType; - protected TabularDataSupport _bindingList; + private final CopyOnWriteArrayList<Binding> _bindings = new CopyOnWriteArrayList<Binding>(); + private final ExchangeType<? extends Exchange> _type; + private UUID _id; + private final AtomicInteger _bindingCountHigh = new AtomicInteger(); + private final AtomicLong _receivedMessageCount = new AtomicLong(); + private final AtomicLong _receivedMessageSize = new AtomicLong(); + private final AtomicLong _routedMessageCount = new AtomicLong(); + private final AtomicLong _routedMessageSize = new AtomicLong(); + private final CopyOnWriteArrayList<Exchange.BindingListener> _listeners = new CopyOnWriteArrayList<Exchange.BindingListener>(); +/* +======= public ExchangeMBean() throws NotCompliantMBeanException { super(ManagedExchange.class, ManagedExchange.TYPE); } +>>>>>>> .r902547 +*/ - protected void init() throws OpenDataException - { - _bindingItemTypes = new OpenType[2]; - _bindingItemTypes[0] = SimpleType.STRING; - _bindingItemTypes[1] = new ArrayType(1, SimpleType.STRING); - _bindingDataType = new CompositeType("Exchange Binding", "Binding key and Queue names", - COMPOSITE_ITEM_NAMES, COMPOSITE_ITEM_DESCRIPTIONS, _bindingItemTypes); - _bindinglistDataType = new TabularType("Exchange Bindings", "Exchange Bindings for " + getName(), - _bindingDataType, TABULAR_UNIQUE_INDEX); - } - - public ManagedObject getParentObject() - { - return _virtualHost.getManagedObject(); - } - - public String getObjectInstanceName() - { - return _name.toString(); - } - - public String getName() - { - return _name.toString(); - } - - public String getExchangeType() - { - return _exchangeType; - } - - public Integer getTicketNo() - { - return _ticket; - } - - public boolean isDurable() - { - return _durable; - } - - public boolean isAutoDelete() - { - return _autoDelete; - } - - // Added exchangetype in the object name lets maangement apps to do any customization required - public ObjectName getObjectName() throws MalformedObjectNameException - { - String objNameString = super.getObjectName().toString(); - objNameString = objNameString + ",ExchangeType=" + _exchangeType; - return new ObjectName(objNameString); - } + // TODO + private long _createTime = System.currentTimeMillis(); - protected ManagedObjectRegistry getManagedObjectRegistry() - { - return ApplicationRegistry.getInstance().getManagedObjectRegistry(); - } - } // End of MBean class + public AbstractExchange(final ExchangeType<? extends Exchange> type) + { + _type = type; + } - public AMQShortString getName() + public AMQShortString getNameShortString() { return _name; } + public final AMQShortString getTypeShortString() + { + return _type.getName(); + } + /** * Concrete exchanges must implement this method in order to create the managed representation. This is * called during initialisation (template method pattern). * @return the MBean */ - protected abstract ExchangeMBean createMBean() throws JMException; + protected abstract AbstractExchangeMBean createMBean() throws JMException; public void initialise(VirtualHost host, AMQShortString name, boolean durable, int ticket, boolean autoDelete) throws AMQException @@ -173,6 +133,11 @@ public abstract class AbstractExchange implements Exchange, Managable _durable = durable; _autoDelete = autoDelete; _ticket = ticket; + + // TODO - fix + _id = getConfigStore().createId(); + + getConfigStore().addConfiguredObject(this); try { _exchangeMbean = createMBean(); @@ -185,7 +150,12 @@ public abstract class AbstractExchange implements Exchange, Managable _logSubject = new ExchangeLogSubject(this, this.getVirtualHost()); // Log Exchange creation - CurrentActor.get().message(ExchangeMessages.EXH_CREATED(String.valueOf(getType()), String.valueOf(name), durable)); + CurrentActor.get().message(ExchangeMessages.EXH_CREATED(String.valueOf(getTypeShortString()), String.valueOf(name), durable)); + } + + public ConfigStore getConfigStore() + { + return getVirtualHost().getConfigStore(); } public abstract Logger getLogger(); @@ -207,21 +177,32 @@ public abstract class AbstractExchange implements Exchange, Managable public void close() throws AMQException { - if (_exchangeMbean != null) - { - _exchangeMbean.unregister(); - } - if(_alternateExchange != null) + + if(_closed.compareAndSet(false,true)) { - _alternateExchange.removeReference(this); + if (_exchangeMbean != null) + { + _exchangeMbean.unregister(); + } + getConfigStore().removeConfiguredObject(this); + if(_alternateExchange != null) + { + _alternateExchange.removeReference(this); + } + + CurrentActor.get().message(_logSubject, ExchangeMessages.EXH_DELETED()); + + for(Task task : _closeTaskList) + { + task.onClose(this); + } + _closeTaskList.clear(); } - - CurrentActor.get().message(_logSubject, ExchangeMessages.EXH_DELETED()); } public String toString() { - return getClass().getSimpleName() + "[" + getName() +"]"; + return getClass().getSimpleName() + "[" + getNameShortString() +"]"; } public ManagedObject getManagedObject() @@ -288,4 +269,143 @@ public abstract class AbstractExchange implements Exchange, Managable { return !_referrers.isEmpty(); } + + public void addCloseTask(final Task task) + { + _closeTaskList.add(task); + } + + public void removeCloseTask(final Task task) + { + _closeTaskList.remove(task); + } + + public final void addBinding(final Binding binding) + { + _bindings.add(binding); + int bindingCountSize = _bindings.size(); + int maxBindingsSize; + while((maxBindingsSize = _bindingCountHigh.get()) < bindingCountSize) + { + _bindingCountHigh.compareAndSet(maxBindingsSize, bindingCountSize); + } + for(BindingListener listener : _listeners) + { + listener.bindingAdded(this, binding); + } + onBind(binding); + } + + public long getBindingCountHigh() + { + return _bindingCountHigh.get(); + } + + public final void removeBinding(final Binding binding) + { + onUnbind(binding); + for(BindingListener listener : _listeners) + { + listener.bindingRemoved(this, binding); + } + _bindings.remove(binding); + } + + public final Collection<Binding> getBindings() + { + return Collections.unmodifiableList(_bindings); + } + + protected abstract void onBind(final Binding binding); + + protected abstract void onUnbind(final Binding binding); + + + public String getName() + { + return _name.toString(); + } + + public ExchangeType getType() + { + return _type; + } + + public Map<String, Object> getArguments() + { + // TODO - Fix + return Collections.EMPTY_MAP; + } + + public UUID getId() + { + return _id; + } + + public ExchangeConfigType getConfigType() + { + return ExchangeConfigType.getInstance(); + } + + public ConfiguredObject getParent() + { + return _virtualHost; + } + + public long getBindingCount() + { + return getBindings().size(); + } + + + + public final ArrayList<? extends BaseQueue> route(final InboundMessage message) + { + _receivedMessageCount.incrementAndGet(); + _receivedMessageSize.addAndGet(message.getSize()); + final ArrayList<? extends BaseQueue> queues = doRoute(message); + if(queues != null && !queues.isEmpty()) + { + _routedMessageCount.incrementAndGet(); + _routedMessageSize.addAndGet(message.getSize()); + } + return queues; + } + + protected abstract ArrayList<? extends BaseQueue> doRoute(final InboundMessage message); + + public long getMsgReceives() + { + return _receivedMessageCount.get(); + } + + public long getMsgRoutes() + { + return _routedMessageCount.get(); + } + + public long getByteReceives() + { + return _receivedMessageSize.get(); + } + + public long getByteRoutes() + { + return _routedMessageSize.get(); + } + + public long getCreateTime() + { + return _createTime; + } + + public void addBindingListener(final BindingListener listener) + { + _listeners.add(listener); + } + + public void removeBindingListener(final BindingListener listener) + { + _listeners.remove(listener); + } } diff --git a/java/broker/src/main/java/org/apache/qpid/server/exchange/AbstractExchangeMBean.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/AbstractExchangeMBean.java new file mode 100644 index 0000000000..ece8bc90fe --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/exchange/AbstractExchangeMBean.java @@ -0,0 +1,139 @@ +/* + * + * 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.exchange; + +import org.apache.qpid.server.management.AMQManagedObject; +import org.apache.qpid.server.management.ManagedObject; +import org.apache.qpid.server.management.ManagedObjectRegistry; +import org.apache.qpid.server.registry.ApplicationRegistry; +import org.apache.qpid.server.virtualhost.VirtualHost; +import org.apache.qpid.server.queue.AMQQueue; +import org.apache.qpid.server.logging.actors.CurrentActor; +import org.apache.qpid.server.logging.actors.ManagementActor; +import org.apache.qpid.management.common.mbeans.ManagedExchange; +import org.apache.qpid.framing.AMQShortString; + +import javax.management.openmbean.*; +import javax.management.NotCompliantMBeanException; +import javax.management.ObjectName; +import javax.management.MalformedObjectNameException; +import javax.management.JMException; + +/** + * Abstract MBean class. This has some of the methods implemented from + * management intrerface for exchanges. Any implementaion of an + * Exchange MBean should extend this class. + */ +public abstract class AbstractExchangeMBean<T extends AbstractExchange> extends AMQManagedObject implements ManagedExchange +{ + // open mbean data types for representing exchange bindings + protected OpenType[] _bindingItemTypes; + protected CompositeType _bindingDataType; + protected TabularType _bindinglistDataType; + + + private T _exchange; + + public AbstractExchangeMBean(final T abstractExchange) throws NotCompliantMBeanException + { + super(ManagedExchange.class, ManagedExchange.TYPE); + _exchange = abstractExchange; + } + + protected void init() throws OpenDataException + { + _bindingItemTypes = new OpenType[2]; + _bindingItemTypes[0] = SimpleType.STRING; + _bindingItemTypes[1] = new ArrayType(1, SimpleType.STRING); + _bindingDataType = new CompositeType("Exchange Binding", "Binding key and Queue names", + COMPOSITE_ITEM_NAMES, COMPOSITE_ITEM_DESCRIPTIONS, _bindingItemTypes); + _bindinglistDataType = new TabularType("Exchange Bindings", "Exchange Bindings for " + getName(), + _bindingDataType, TABULAR_UNIQUE_INDEX); + } + + public ManagedObject getParentObject() + { + return _exchange.getVirtualHost().getManagedObject(); + } + + public T getExchange() + { + return _exchange; + } + + + public String getObjectInstanceName() + { + return _exchange.getNameShortString().toString(); + } + + public String getName() + { + return _exchange.getNameShortString().toString(); + } + + public String getExchangeType() + { + return _exchange.getTypeShortString().toString(); + } + + public Integer getTicketNo() + { + return _exchange._ticket; + } + + public boolean isDurable() + { + return _exchange._durable; + } + + public boolean isAutoDelete() + { + return _exchange._autoDelete; + } + + // Added exchangetype in the object name lets maangement apps to do any customization required + public ObjectName getObjectName() throws MalformedObjectNameException + { + String objNameString = super.getObjectName().toString(); + objNameString = objNameString + ",ExchangeType=" + getExchangeType(); + return new ObjectName(objNameString); + } + + protected ManagedObjectRegistry getManagedObjectRegistry() + { + return ApplicationRegistry.getInstance().getManagedObjectRegistry(); + } + + public void createNewBinding(String queueName, String binding) throws JMException + { + VirtualHost vhost = getExchange().getVirtualHost(); + AMQQueue queue = vhost.getQueueRegistry().getQueue(new AMQShortString(queueName)); + if (queue == null) + { + throw new JMException("Queue \"" + queueName + "\" is not registered with the exchange."); + } + + CurrentActor.set(new ManagementActor(_logActor.getRootMessageLogger())); + vhost.getBindingFactory().addBinding(binding,queue,getExchange(),null); + CurrentActor.remove(); + } +} // End of MBean class diff --git a/java/broker/src/main/java/org/apache/qpid/server/exchange/DefaultExchangeFactory.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/DefaultExchangeFactory.java index 6b0cf89b95..1c4c341c14 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/exchange/DefaultExchangeFactory.java +++ b/java/broker/src/main/java/org/apache/qpid/server/exchange/DefaultExchangeFactory.java @@ -20,19 +20,20 @@ */ package org.apache.qpid.server.exchange; -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; - import org.apache.log4j.Logger; import org.apache.qpid.AMQException; import org.apache.qpid.AMQUnknownExchangeType; import org.apache.qpid.framing.AMQShortString; +import org.apache.qpid.qmf.ManagementExchange; import org.apache.qpid.server.configuration.VirtualHostConfiguration; import org.apache.qpid.server.registry.ApplicationRegistry; import org.apache.qpid.server.virtualhost.VirtualHost; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + public class DefaultExchangeFactory implements ExchangeFactory { private static final Logger _logger = Logger.getLogger(DefaultExchangeFactory.class); @@ -47,6 +48,7 @@ public class DefaultExchangeFactory implements ExchangeFactory registerExchangeType(TopicExchange.TYPE); registerExchangeType(HeadersExchange.TYPE); registerExchangeType(FanoutExchange.TYPE); + registerExchangeType(ManagementExchange.TYPE); } public void registerExchangeType(ExchangeType<? extends Exchange> type) diff --git a/java/broker/src/main/java/org/apache/qpid/server/exchange/DefaultExchangeRegistry.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/DefaultExchangeRegistry.java index 7b21ad6b91..84444450c9 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/exchange/DefaultExchangeRegistry.java +++ b/java/broker/src/main/java/org/apache/qpid/server/exchange/DefaultExchangeRegistry.java @@ -66,8 +66,8 @@ public class DefaultExchangeRegistry implements ExchangeRegistry public void registerExchange(Exchange exchange) throws AMQException { - _exchangeMap.put(exchange.getName(), exchange); - _exchangeMapStr.put(exchange.getName().toString(), exchange); + _exchangeMap.put(exchange.getNameShortString(), exchange); + _exchangeMapStr.put(exchange.getNameShortString().toString(), exchange); } public void setDefaultExchange(Exchange exchange) diff --git a/java/broker/src/main/java/org/apache/qpid/server/exchange/DirectExchange.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/DirectExchange.java index 3c3902c545..cb0d8ecf8f 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/exchange/DirectExchange.java +++ b/java/broker/src/main/java/org/apache/qpid/server/exchange/DirectExchange.java @@ -20,40 +20,29 @@ */ package org.apache.qpid.server.exchange; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -import javax.management.JMException; -import javax.management.MBeanException; -import javax.management.openmbean.CompositeData; -import javax.management.openmbean.CompositeDataSupport; -import javax.management.openmbean.OpenDataException; -import javax.management.openmbean.TabularData; -import javax.management.openmbean.TabularDataSupport; - import org.apache.log4j.Logger; + import org.apache.qpid.AMQException; -import org.apache.qpid.management.common.mbeans.annotations.MBeanConstructor; -import org.apache.qpid.management.common.mbeans.annotations.MBeanDescription; -import org.apache.qpid.protocol.AMQConstant; import org.apache.qpid.exchange.ExchangeDefaults; import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.framing.FieldTable; +import org.apache.qpid.server.binding.Binding; +import org.apache.qpid.server.message.InboundMessage; import org.apache.qpid.server.queue.AMQQueue; +import org.apache.qpid.server.queue.BaseQueue; import org.apache.qpid.server.virtualhost.VirtualHost; -import org.apache.qpid.server.message.InboundMessage; -import org.apache.qpid.server.logging.actors.CurrentActor; -import org.apache.qpid.server.logging.actors.ManagementActor; + +import javax.management.JMException; +import java.util.ArrayList; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.CopyOnWriteArraySet; public class DirectExchange extends AbstractExchange { private static final Logger _logger = Logger.getLogger(DirectExchange.class); - /** - * Maps from queue name to queue instances - */ - private final Index _index = new Index(); + private final ConcurrentHashMap<String, CopyOnWriteArraySet<Binding>> _bindingsByKey = + new ConcurrentHashMap<String, CopyOnWriteArraySet<Binding>>(); public static final ExchangeType<DirectExchange> TYPE = new ExchangeType<DirectExchange>() { @@ -85,73 +74,15 @@ public class DirectExchange extends AbstractExchange } }; - /** - * MBean class implementing the management interfaces. - */ - @MBeanDescription("Management Bean for Direct Exchange") - private final class DirectExchangeMBean extends ExchangeMBean - { - @MBeanConstructor("Creates an MBean for AMQ direct exchange") - public DirectExchangeMBean() throws JMException - { - super(); - _exchangeType = "direct"; - init(); - } - - public TabularData bindings() throws OpenDataException - { - Map<AMQShortString, List<AMQQueue>> bindings = _index.getBindingsMap(); - _bindingList = new TabularDataSupport(_bindinglistDataType); - - for (Map.Entry<AMQShortString, List<AMQQueue>> entry : bindings.entrySet()) - { - AMQShortString key = entry.getKey(); - List<String> queueList = new ArrayList<String>(); - - List<AMQQueue> queues = entry.getValue(); - for (AMQQueue q : queues) - { - queueList.add(q.getName().toString()); - } - - Object[] bindingItemValues = {key.toString(), queueList.toArray(new String[0])}; - CompositeData bindingData = new CompositeDataSupport(_bindingDataType, COMPOSITE_ITEM_NAMES, bindingItemValues); - _bindingList.put(bindingData); - } - - return _bindingList; - } - - public void createNewBinding(String queueName, String binding) throws JMException - { - AMQQueue queue = getQueueRegistry().getQueue(new AMQShortString(queueName)); - if (queue == null) - { - throw new JMException("Queue \"" + queueName + "\" is not registered with the exchange."); - } - - CurrentActor.set(new ManagementActor(_logActor.getRootMessageLogger())); - try - { - queue.bind(DirectExchange.this, new AMQShortString(binding), null); - } - catch (AMQException ex) - { - throw new MBeanException(ex); - } - finally - { - CurrentActor.remove(); - } - } - - }// End of MBean class + public DirectExchange() + { + super(TYPE); + } - protected ExchangeMBean createMBean() throws JMException + protected AbstractExchangeMBean createMBean() throws JMException { - return new DirectExchangeMBean(); + return new DirectExchangeMBean(this); } public Logger getLogger() @@ -159,68 +90,36 @@ public class DirectExchange extends AbstractExchange return _logger; } - public AMQShortString getType() - { - return ExchangeDefaults.DIRECT_EXCHANGE_CLASS; - } - public void registerQueue(String routingKey, AMQQueue queue, Map<String,Object> args) throws AMQException + public ArrayList<? extends BaseQueue> doRoute(InboundMessage payload) { - registerQueue(new AMQShortString(routingKey), queue); - } - public void registerQueue(AMQShortString routingKey, AMQQueue queue, FieldTable args) throws AMQException - { - registerQueue(routingKey, queue); - } + final String routingKey = payload.getRoutingKey(); - private void registerQueue(AMQShortString routingKey, AMQQueue queue) throws AMQException - { - assert queue != null; - assert routingKey != null; - if (!_index.add(routingKey, queue)) + CopyOnWriteArraySet<Binding> bindings = _bindingsByKey.get(routingKey == null ? "" : routingKey); + + if(bindings != null) { - if (_logger.isDebugEnabled()) + final ArrayList<BaseQueue> queues = new ArrayList<BaseQueue>(bindings.size()); + + for(Binding binding : bindings) { - _logger.debug("Queue (" + queue + ") is already registered with routing key " + routingKey); + queues.add(binding.getQueue()); + binding.incrementMatches(); } - } - else - { + if (_logger.isDebugEnabled()) { - _logger.debug("Binding queue:" + queue + " with routing key '" + routingKey +"' to exchange:" + this); + _logger.debug("Publishing message to queue " + queues); } - } - } - public void deregisterQueue(AMQShortString routingKey, AMQQueue queue, FieldTable args) throws AMQException - { - assert queue != null; - assert routingKey != null; - - if (!_index.remove(routingKey, queue)) - { - throw new AMQException(AMQConstant.NOT_FOUND, "Queue " + queue + " was not registered with exchange " + this.getName() + - " with routing key " + routingKey + ". No queue was registered with that _routing key"); + return queues; } - } - - public ArrayList<AMQQueue> route(InboundMessage payload) - { - - final String routingKey = payload.getRoutingKey(); - - - final ArrayList<AMQQueue> queues = (routingKey == null) ? _index.get("") : _index.get(routingKey); - - if (_logger.isDebugEnabled()) + else { - _logger.debug("Publishing message to queue " + queues); + return new ArrayList<BaseQueue>(0); } - return queues; - } @@ -232,24 +131,40 @@ public class DirectExchange extends AbstractExchange public boolean isBound(AMQShortString routingKey, AMQQueue queue) { - final List<AMQQueue> queues = _index.get(routingKey); - return queues != null && queues.contains(queue); + String bindingKey = (routingKey == null) ? "" : routingKey.toString(); + CopyOnWriteArraySet<Binding> bindings = _bindingsByKey.get(bindingKey); + if(bindings != null) + { + for(Binding binding : bindings) + { + if(binding.getQueue().equals(queue)) + { + return true; + } + } + } + return false; + } public boolean isBound(AMQShortString routingKey) { - final List<AMQQueue> queues = _index.get(routingKey); - return queues != null && !queues.isEmpty(); + String bindingKey = (routingKey == null) ? "" : routingKey.toString(); + CopyOnWriteArraySet<Binding> bindings = _bindingsByKey.get(bindingKey); + return bindings != null && !bindings.isEmpty(); } public boolean isBound(AMQQueue queue) { - Map<AMQShortString, List<AMQQueue>> bindings = _index.getBindingsMap(); - for (List<AMQQueue> queues : bindings.values()) + + for (CopyOnWriteArraySet<Binding> bindings : _bindingsByKey.values()) { - if (queues.contains(queue)) + for(Binding binding : bindings) { - return true; + if(binding.getQueue().equals(queue)) + { + return true; + } } } return false; @@ -257,11 +172,45 @@ public class DirectExchange extends AbstractExchange public boolean hasBindings() { - return !_index.getBindingsMap().isEmpty(); + return !getBindings().isEmpty(); } - public Map<AMQShortString, List<AMQQueue>> getBindings() + protected void onBind(final Binding binding) { - return _index.getBindingsMap(); + String bindingKey = binding.getBindingKey(); + AMQQueue queue = binding.getQueue(); + AMQShortString routingKey = AMQShortString.valueOf(bindingKey); + + assert queue != null; + assert routingKey != null; + + CopyOnWriteArraySet<Binding> bindings = _bindingsByKey.get(bindingKey); + + if(bindings == null) + { + bindings = new CopyOnWriteArraySet<Binding>(); + CopyOnWriteArraySet<Binding> newBindings; + if((newBindings = _bindingsByKey.putIfAbsent(bindingKey, bindings)) != null) + { + bindings = newBindings; + } + } + + bindings.add(binding); + + } + + protected void onUnbind(final Binding binding) + { + assert binding != null; + + CopyOnWriteArraySet<Binding> bindings = _bindingsByKey.get(binding.getBindingKey()); + if(bindings != null) + { + bindings.remove(binding); + } + } + + } diff --git a/java/broker/src/main/java/org/apache/qpid/server/exchange/DirectExchangeMBean.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/DirectExchangeMBean.java new file mode 100644 index 0000000000..086832c045 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/exchange/DirectExchangeMBean.java @@ -0,0 +1,79 @@ +/* + * + * 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.exchange; + +import org.apache.qpid.management.common.mbeans.annotations.MBeanDescription; +import org.apache.qpid.management.common.mbeans.annotations.MBeanConstructor; +import org.apache.qpid.server.binding.Binding; + +import javax.management.JMException; +import javax.management.openmbean.*; +import java.util.List; +import java.util.Map; +import java.util.ArrayList; +import java.util.HashMap; + +/** + * MBean class implementing the management interfaces. + */ +@MBeanDescription("Management Bean for Direct Exchange") +final class DirectExchangeMBean extends AbstractExchangeMBean<DirectExchange> +{ + @MBeanConstructor("Creates an MBean for AMQ direct exchange") + public DirectExchangeMBean(final DirectExchange exchange) throws JMException + { + super(exchange); + + init(); + } + + public TabularData bindings() throws OpenDataException + { + TabularDataSupport bindingList = new TabularDataSupport(_bindinglistDataType); + + Map<String, List<String>> bindingMap = new HashMap<String, List<String>>(); + + for (Binding binding : getExchange().getBindings()) + { + String key = binding.getBindingKey(); + List<String> queueList = bindingMap.get(key); + if(queueList == null) + { + queueList = new ArrayList<String>(); + bindingMap.put(key, queueList); + } + queueList.add(binding.getQueue().getNameShortString().toString()); + + } + + for(Map.Entry<String, List<String>> entry : bindingMap.entrySet()) + { + Object[] bindingItemValues = {entry.getKey(), entry.getValue().toArray(new String[0])}; + CompositeData bindingData = new CompositeDataSupport(_bindingDataType, COMPOSITE_ITEM_NAMES, bindingItemValues); + bindingList.put(bindingData); + } + + return bindingList; + } + + + +}// End of MBean class diff --git a/java/broker/src/main/java/org/apache/qpid/server/exchange/Exchange.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/Exchange.java index 4bbdeaef1c..8a31b1bab1 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/exchange/Exchange.java +++ b/java/broker/src/main/java/org/apache/qpid/server/exchange/Exchange.java @@ -25,17 +25,31 @@ import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.framing.FieldTable; import org.apache.qpid.server.queue.AMQQueue; +import org.apache.qpid.server.queue.BaseQueue; import org.apache.qpid.server.virtualhost.VirtualHost; import org.apache.qpid.server.message.InboundMessage; +import org.apache.qpid.server.binding.BindingFactory; +import org.apache.qpid.server.binding.Binding; +import org.apache.qpid.server.configuration.ExchangeConfig; import javax.management.JMException; import java.util.ArrayList; +import java.util.List; +import java.util.Collection; +import java.util.concurrent.CopyOnWriteArrayList; -public interface Exchange extends ExchangeReferrer +public interface Exchange extends ExchangeReferrer, ExchangeConfig { - AMQShortString getName(); - AMQShortString getType(); + public interface BindingListener + { + void bindingAdded(Exchange exchange, Binding binding); + void bindingRemoved(Exchange exchange, Binding binding); + } + + AMQShortString getNameShortString(); + + AMQShortString getTypeShortString(); void initialise(VirtualHost host, AMQShortString name, boolean durable, int ticket, boolean autoDelete) throws AMQException, JMException; @@ -51,13 +65,8 @@ public interface Exchange extends ExchangeReferrer void close() throws AMQException; - void registerQueue(AMQShortString routingKey, AMQQueue queue, FieldTable args) throws AMQException; - - - void deregisterQueue(AMQShortString routingKey, AMQQueue queue, FieldTable args) throws AMQException; - - ArrayList<AMQQueue> route(InboundMessage message); + ArrayList<? extends BaseQueue> route(InboundMessage message); /** @@ -101,6 +110,11 @@ public interface Exchange extends ExchangeReferrer boolean isBound(String bindingKey); + void addCloseTask(Task task); + + void removeCloseTask(Task task); + + Exchange getAlternateExchange(); void setAlternateExchange(Exchange exchange); @@ -110,4 +124,20 @@ public interface Exchange extends ExchangeReferrer void addReference(ExchangeReferrer exchange); boolean hasReferrers(); + + void addBinding(Binding binding); + + void removeBinding(Binding binding); + + Collection<Binding> getBindings(); + + public void addBindingListener(BindingListener listener); + + public void removeBindingListener(BindingListener listener); + + + public static interface Task + { + public void onClose(Exchange exchange); + } } diff --git a/java/broker/src/main/java/org/apache/qpid/server/exchange/FanoutExchange.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/FanoutExchange.java index 00f8ebd856..bd75f7bc51 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/exchange/FanoutExchange.java +++ b/java/broker/src/main/java/org/apache/qpid/server/exchange/FanoutExchange.java @@ -21,109 +21,35 @@ package org.apache.qpid.server.exchange; import org.apache.log4j.Logger; + import org.apache.qpid.AMQException; -import org.apache.qpid.management.common.mbeans.annotations.MBeanConstructor; -import org.apache.qpid.management.common.mbeans.annotations.MBeanDescription; -import org.apache.qpid.protocol.AMQConstant; import org.apache.qpid.exchange.ExchangeDefaults; import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.framing.FieldTable; +import org.apache.qpid.server.binding.Binding; +import org.apache.qpid.server.message.InboundMessage; import org.apache.qpid.server.queue.AMQQueue; +import org.apache.qpid.server.queue.BaseQueue; import org.apache.qpid.server.virtualhost.VirtualHost; -import org.apache.qpid.server.message.InboundMessage; -import org.apache.qpid.server.logging.actors.CurrentActor; -import org.apache.qpid.server.logging.actors.ManagementActor; import javax.management.JMException; -import javax.management.MBeanException; -import javax.management.openmbean.CompositeData; -import javax.management.openmbean.CompositeDataSupport; -import javax.management.openmbean.OpenDataException; -import javax.management.openmbean.TabularData; -import javax.management.openmbean.TabularDataSupport; -import java.util.List; -import java.util.Map; import java.util.ArrayList; -import java.util.concurrent.CopyOnWriteArraySet; +import java.util.concurrent.ConcurrentHashMap; public class FanoutExchange extends AbstractExchange { private static final Logger _logger = Logger.getLogger(FanoutExchange.class); + private static final Integer ONE = Integer.valueOf(1); + /** * Maps from queue name to queue instances */ - private final CopyOnWriteArraySet<AMQQueue> _queues = new CopyOnWriteArraySet<AMQQueue>(); + private final ConcurrentHashMap<AMQQueue,Integer> _queues = new ConcurrentHashMap<AMQQueue,Integer>(); - /** - * MBean class implementing the management interfaces. - */ - @MBeanDescription("Management Bean for Fanout Exchange") - private final class FanoutExchangeMBean extends ExchangeMBean + protected AbstractExchangeMBean createMBean() throws JMException { - private static final String BINDING_KEY_SUBSTITUTE = "*"; - - @MBeanConstructor("Creates an MBean for AMQ fanout exchange") - public FanoutExchangeMBean() throws JMException - { - super(); - _exchangeType = "fanout"; - init(); - } - - public TabularData bindings() throws OpenDataException - { - - _bindingList = new TabularDataSupport(_bindinglistDataType); - - if(_queues.isEmpty()) - { - return _bindingList; - } - - ArrayList<String> queueNames = new ArrayList<String>(); - - for (AMQQueue queue : _queues) - { - String queueName = queue.getName().toString(); - queueNames.add(queueName); - } - - Object[] bindingItemValues = {BINDING_KEY_SUBSTITUTE, queueNames.toArray(new String[0])}; - CompositeData bindingData = new CompositeDataSupport(_bindingDataType, COMPOSITE_ITEM_NAMES, bindingItemValues); - _bindingList.put(bindingData); - - return _bindingList; - } - - public void createNewBinding(String queueName, String binding) throws JMException - { - AMQQueue queue = getQueueRegistry().getQueue(new AMQShortString(queueName)); - if (queue == null) - { - throw new JMException("Queue \"" + queueName + "\" is not registered with the exchange."); - } - - CurrentActor.set(new ManagementActor(_logActor.getRootMessageLogger())); - try - { - queue.bind(FanoutExchange.this, new AMQShortString(BINDING_KEY_SUBSTITUTE), null); - } - catch (AMQException ex) - { - throw new MBeanException(ex); - } - finally - { - CurrentActor.remove(); - } - } - - } // End of MBean class - - protected ExchangeMBean createMBean() throws JMException - { - return new FanoutExchange.FanoutExchangeMBean(); + return new FanoutExchangeMBean(this); } public Logger getLogger() @@ -161,51 +87,26 @@ public class FanoutExchange extends AbstractExchange } }; - public Map<AMQShortString, List<AMQQueue>> getBindings() + public FanoutExchange() { - return null; + super(TYPE); } - public AMQShortString getType() + public ArrayList<BaseQueue> doRoute(InboundMessage payload) { - return ExchangeDefaults.FANOUT_EXCHANGE_CLASS; - } - - public void registerQueue(AMQShortString routingKey, AMQQueue queue, FieldTable args) throws AMQException - { - assert queue != null; - if (_queues.contains(queue)) - { - _logger.debug("Queue " + queue + " is already registered"); - } - else - { - _queues.add(queue); - _logger.debug("Binding queue " + queue + " with routing key " + routingKey + " to exchange " + this); - } - } - public void deregisterQueue(AMQShortString routingKey, AMQQueue queue, FieldTable args) throws AMQException - { - assert queue != null; - - if (!_queues.remove(queue)) + if (_logger.isDebugEnabled()) { - throw new AMQException(AMQConstant.NOT_FOUND, "Queue " + queue + " was not registered with exchange " + this.getName() + ". "); + _logger.debug("Publishing message to queue " + _queues); } - } - public ArrayList<AMQQueue> route(InboundMessage payload) - { - - - if (_logger.isDebugEnabled()) + for(Binding b : getBindings()) { - _logger.debug("Publishing message to queue " + _queues); + b.incrementMatches(); } - return new ArrayList(_queues); + return new ArrayList<BaseQueue>(_queues.keySet()); } @@ -235,4 +136,71 @@ public class FanoutExchange extends AbstractExchange { return !_queues.isEmpty(); } + + protected void onBind(final Binding binding) + { + AMQQueue queue = binding.getQueue(); + assert queue != null; + + Integer oldVal; + + if((oldVal = _queues.putIfAbsent(queue, ONE)) != null) + { + Integer newVal = oldVal+1; + while(!_queues.replace(queue, oldVal, newVal)) + { + oldVal = _queues.get(queue); + if(oldVal == null) + { + oldVal = _queues.putIfAbsent(queue, ONE); + if(oldVal == null) + { + break; + } + } + newVal = oldVal + 1; + } + } + + if (_logger.isDebugEnabled()) + { + _logger.debug("Binding queue " + queue + + " with routing key " + new AMQShortString(binding.getBindingKey()) + " to exchange " + this); + } + } + + protected void onUnbind(final Binding binding) + { + AMQQueue queue = binding.getQueue(); + Integer oldValue = _queues.get(queue); + + boolean done = false; + + while(!(done || oldValue == null)) + { + while(!(done || oldValue == null) && oldValue.intValue() == 1) + { + if(!_queues.remove(queue, oldValue)) + { + oldValue = _queues.get(queue); + } + else + { + done = true; + } + } + while(!(done || oldValue == null) && oldValue.intValue() != 1) + { + Integer newValue = oldValue - 1; + if(!_queues.replace(queue, oldValue, newValue)) + { + oldValue = _queues.get(queue); + } + else + { + done = true; + } + } + } + } } diff --git a/java/broker/src/main/java/org/apache/qpid/server/exchange/FanoutExchangeMBean.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/FanoutExchangeMBean.java new file mode 100644 index 0000000000..d5734f76a5 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/exchange/FanoutExchangeMBean.java @@ -0,0 +1,68 @@ +/* + * + * 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.exchange; + +import org.apache.qpid.management.common.mbeans.annotations.MBeanDescription; +import org.apache.qpid.management.common.mbeans.annotations.MBeanConstructor; +import org.apache.qpid.server.binding.Binding; + +import javax.management.JMException; +import javax.management.openmbean.*; +import java.util.ArrayList; + +/** + * MBean class implementing the management interfaces. + */ +@MBeanDescription("Management Bean for Fanout Exchange") +final class FanoutExchangeMBean extends AbstractExchangeMBean<FanoutExchange> +{ + private static final String BINDING_KEY_SUBSTITUTE = "*"; + + @MBeanConstructor("Creates an MBean for AMQ fanout exchange") + public FanoutExchangeMBean(final FanoutExchange exchange) throws JMException + { + super(exchange); + init(); + } + + public TabularData bindings() throws OpenDataException + { + + TabularDataSupport bindingList = new TabularDataSupport(_bindinglistDataType); + + + ArrayList<String> queueNames = new ArrayList<String>(); + + for (Binding binding : getExchange().getBindings()) + { + String queueName = binding.getQueue().getNameShortString().toString(); + queueNames.add(queueName); + } + + Object[] bindingItemValues = {BINDING_KEY_SUBSTITUTE, queueNames.toArray(new String[0])}; + CompositeData bindingData = new CompositeDataSupport(_bindingDataType, COMPOSITE_ITEM_NAMES, bindingItemValues); + bindingList.put(bindingData); + + return bindingList; + } + + +} // End of MBean class diff --git a/java/broker/src/main/java/org/apache/qpid/server/exchange/HeadersExchange.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/HeadersExchange.java index 5677cc4510..ce0b14932f 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/exchange/HeadersExchange.java +++ b/java/broker/src/main/java/org/apache/qpid/server/exchange/HeadersExchange.java @@ -22,33 +22,20 @@ package org.apache.qpid.server.exchange; import org.apache.log4j.Logger; import org.apache.qpid.AMQException; -import org.apache.qpid.management.common.mbeans.annotations.MBeanConstructor; -import org.apache.qpid.management.common.mbeans.annotations.MBeanDescription; -import org.apache.qpid.protocol.AMQConstant; import org.apache.qpid.exchange.ExchangeDefaults; import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.framing.AMQTypedValue; import org.apache.qpid.framing.BasicContentHeaderProperties; import org.apache.qpid.framing.ContentHeaderBody; import org.apache.qpid.framing.FieldTable; import org.apache.qpid.server.queue.AMQQueue; +import org.apache.qpid.server.queue.BaseQueue; import org.apache.qpid.server.virtualhost.VirtualHost; import org.apache.qpid.server.message.InboundMessage; import org.apache.qpid.server.message.AMQMessageHeader; +import org.apache.qpid.server.binding.Binding; import javax.management.JMException; -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.util.ArrayList; -import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.concurrent.CopyOnWriteArrayList; @@ -119,151 +106,40 @@ public class HeadersExchange extends AbstractExchange private final List<Registration> _bindings = new CopyOnWriteArrayList<Registration>(); private Map<AMQShortString, Registration> _bindingByKey = new ConcurrentHashMap<AMQShortString, Registration>(); - /** - * HeadersExchangeMBean class implements the management interface for the - * Header Exchanges. - */ - @MBeanDescription("Management Bean for Headers Exchange") - private final class HeadersExchangeMBean extends ExchangeMBean - { - @MBeanConstructor("Creates an MBean for AMQ Headers exchange") - public HeadersExchangeMBean() throws JMException - { - super(); - _exchangeType = "headers"; - init(); - } - - /** - * initialises the OpenType objects. - */ - protected void init() throws OpenDataException - { - - _bindingItemTypes = new OpenType[3]; - _bindingItemTypes[0] = SimpleType.INTEGER; - _bindingItemTypes[1] = SimpleType.STRING; - _bindingItemTypes[2] = new ArrayType(1, SimpleType.STRING); - _bindingDataType = new CompositeType("Exchange Binding", "Queue name and header bindings", - HEADERS_COMPOSITE_ITEM_NAMES, HEADERS_COMPOSITE_ITEM_DESC, _bindingItemTypes); - _bindinglistDataType = new TabularType("Exchange Bindings", "List of exchange bindings for " + getName(), - _bindingDataType, HEADERS_TABULAR_UNIQUE_INDEX); - } - - public TabularData bindings() throws OpenDataException - { - _bindingList = new TabularDataSupport(_bindinglistDataType); - int count = 1; - for (Iterator<Registration> itr = _bindings.iterator(); itr.hasNext();) - { - Registration registration = itr.next(); - String queueName = registration.queue.getName().toString(); - - HeadersBinding headers = registration.binding; - FieldTable headerMappings = headers.getMappings(); - final List<String> mappingList = new ArrayList<String>(); - - headerMappings.processOverElements(new FieldTable.FieldTableElementProcessor() - { - - public boolean processElement(String propertyName, AMQTypedValue value) - { - mappingList.add(propertyName + "=" + value.getValue()); - return true; - } - - public Object getResult() - { - return mappingList; - } - }); - - Object[] bindingItemValues = {count++, queueName, mappingList.toArray(new String[0])}; - CompositeData bindingData = new CompositeDataSupport(_bindingDataType, HEADERS_COMPOSITE_ITEM_NAMES, bindingItemValues); - _bindingList.put(bindingData); - } - - return _bindingList; - } - - /** - * Creates bindings. Binding pattern is as follows- - * <attributename>=<value>,<attributename>=<value>,... - * @param queueName - * @param binding - * @throws javax.management.JMException - */ - public void createNewBinding(String queueName, String binding) throws JMException - { - AMQQueue queue = getQueueRegistry().getQueue(new AMQShortString(queueName)); - - if (queue == null) - { - throw new JMException("Queue \"" + queueName + "\" is not registered with the exchange."); - } - - String[] bindings = binding.split(","); - FieldTable bindingMap = new FieldTable(); - for (int i = 0; i < bindings.length; i++) - { - String[] keyAndValue = bindings[i].split("="); - if (keyAndValue == null || keyAndValue.length == 0 || keyAndValue.length > 2) - { - 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 - bindingMap.setString(keyAndValue[0], ""); - } - else - { - bindingMap.setString(keyAndValue[0], keyAndValue[1]); - } - } - - _bindings.add(new Registration(new HeadersBinding(bindingMap), queue, new AMQShortString(binding))); - } - - } // End of MBean class + public HeadersExchange() + { + super(TYPE); + } - public AMQShortString getType() + public void registerQueue(String routingKey, AMQQueue queue, Map<String,Object> args) { - return ExchangeDefaults.HEADERS_EXCHANGE_CLASS; + registerQueue(new AMQShortString(routingKey), queue, FieldTable.convertToFieldTable(args)); } - public void registerQueue(AMQShortString routingKey, AMQQueue queue, FieldTable args) throws AMQException + public void registerQueue(AMQShortString routingKey, AMQQueue queue, FieldTable args) { - _logger.debug("Exchange " + getName() + ": Binding " + queue.getName() + " with " + args); + _logger.debug("Exchange " + getNameShortString() + ": Binding " + queue.getNameShortString() + " with " + args); Registration registration = new Registration(new HeadersBinding(args), queue, routingKey); _bindings.add(registration); } - public void deregisterQueue(AMQShortString routingKey, AMQQueue queue, FieldTable args) throws AMQException + public void deregisterQueue(String routingKey, AMQQueue queue, Map<String,Object> args) { - _logger.debug("Exchange " + getName() + ": Unbinding " + queue.getName()); - - if(!_bindings.remove(new Registration(args == null ? null : new HeadersBinding(args), queue, routingKey))) - { - throw new AMQException(AMQConstant.NOT_FOUND, "Queue " + queue + " was not registered with exchange " + this.getName() - + " with headers args " + args); - } + _bindings.remove(new Registration(args == null ? null : new HeadersBinding(FieldTable.convertToFieldTable(args)), queue, new AMQShortString(routingKey))); } - public ArrayList<AMQQueue> route(InboundMessage payload) + public ArrayList<BaseQueue> doRoute(InboundMessage payload) { AMQMessageHeader header = payload.getMessageHeader(); if (_logger.isDebugEnabled()) { - _logger.debug("Exchange " + getName() + ": routing message with headers " + header); + _logger.debug("Exchange " + getNameShortString() + ": routing message with headers " + header); } boolean routed = false; - ArrayList<AMQQueue> queues = new ArrayList<AMQQueue>(); + ArrayList<BaseQueue> queues = new ArrayList<BaseQueue>(); for (Registration e : _bindings) { @@ -271,8 +147,8 @@ public class HeadersExchange extends AbstractExchange { if (_logger.isDebugEnabled()) { - _logger.debug("Exchange " + getName() + ": delivering message with headers " + - header + " to " + e.queue.getName()); + _logger.debug("Exchange " + getNameShortString() + ": delivering message with headers " + + header + " to " + e.queue.getNameShortString()); } queues.add(e.queue); @@ -315,6 +191,8 @@ public class HeadersExchange extends AbstractExchange return !_bindings.isEmpty(); } + + protected FieldTable getHeaders(ContentHeaderBody contentHeaderFrame) { //what if the content type is not 'basic'? 'file' and 'stream' content classes also define headers, @@ -322,14 +200,9 @@ public class HeadersExchange extends AbstractExchange return ((BasicContentHeaderProperties) contentHeaderFrame.properties).getHeaders(); } - protected ExchangeMBean createMBean() throws JMException + protected AbstractExchangeMBean createMBean() throws JMException { - return new HeadersExchangeMBean(); - } - - public Map<AMQShortString, List<AMQQueue>> getBindings() - { - return null; + return new HeadersExchangeMBean(this); } public Logger getLogger() @@ -338,7 +211,7 @@ public class HeadersExchange extends AbstractExchange } - private static class Registration + static class Registration { private final HeadersBinding binding; private final AMQQueue queue; @@ -365,5 +238,31 @@ public class HeadersExchange extends AbstractExchange && (routingKey == null ? ((Registration)o).routingKey == null : routingKey.equals(((Registration)o).routingKey)); } + + public HeadersBinding getBinding() + { + return binding; + } + + public AMQQueue getQueue() + { + return queue; + } + + public AMQShortString getRoutingKey() + { + return routingKey; + } } + + protected void onBind(final Binding binding) + { + registerQueue(binding.getBindingKey(), binding.getQueue(), binding.getArguments()); + } + + protected void onUnbind(final Binding binding) + { + deregisterQueue(binding.getBindingKey(), binding.getQueue(), binding.getArguments()); + } + } diff --git a/java/broker/src/main/java/org/apache/qpid/server/exchange/HeadersExchangeMBean.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/HeadersExchangeMBean.java new file mode 100644 index 0000000000..2c7985b480 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/exchange/HeadersExchangeMBean.java @@ -0,0 +1,96 @@ +/* + * + * 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.exchange; + +import org.apache.qpid.management.common.mbeans.annotations.MBeanDescription; +import org.apache.qpid.management.common.mbeans.annotations.MBeanConstructor; +import org.apache.qpid.server.binding.Binding; + +import javax.management.JMException; +import javax.management.openmbean.*; +import java.util.List; +import java.util.ArrayList; +import java.util.Map; + +/** + * HeadersExchangeMBean class implements the management interface for the + * Header Exchanges. + */ +@MBeanDescription("Management Bean for Headers Exchange") +final class HeadersExchangeMBean extends AbstractExchangeMBean<HeadersExchange> +{ + + @MBeanConstructor("Creates an MBean for AMQ Headers exchange") + public HeadersExchangeMBean(final HeadersExchange headersExchange) throws JMException + { + super(headersExchange); + init(); + } + + /** + * initialises the OpenType objects. + */ + protected void init() throws OpenDataException + { + + _bindingItemTypes = new OpenType[3]; + _bindingItemTypes[0] = SimpleType.INTEGER; + _bindingItemTypes[1] = SimpleType.STRING; + _bindingItemTypes[2] = new ArrayType(1, SimpleType.STRING); + _bindingDataType = new CompositeType("Exchange Binding", "Queue name and header bindings", + HEADERS_COMPOSITE_ITEM_NAMES, HEADERS_COMPOSITE_ITEM_DESC, _bindingItemTypes); + _bindinglistDataType = new TabularType("Exchange Bindings", "List of exchange bindings for " + getName(), + _bindingDataType, HEADERS_TABULAR_UNIQUE_INDEX); + } + + public TabularData bindings() throws OpenDataException + { + TabularDataSupport bindingList = new TabularDataSupport(_bindinglistDataType); + int count = 1; + for (Binding binding : getExchange().getBindings()) + { + + String queueName = binding.getQueue().getNameShortString().toString(); + + + 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(_bindingDataType, HEADERS_COMPOSITE_ITEM_NAMES, bindingItemValues); + bindingList.put(bindingData); + } + + return bindingList; + } + + +} // End of MBean class diff --git a/java/broker/src/main/java/org/apache/qpid/server/exchange/Index.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/Index.java deleted file mode 100644 index 90d04c814a..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/server/exchange/Index.java +++ /dev/null @@ -1,114 +0,0 @@ -/* - * - * 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.exchange; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.ArrayList; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; -import java.util.concurrent.CopyOnWriteArrayList; - -import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.server.queue.AMQQueue; - -/** - * An index of queues against routing key. Allows multiple queues to be stored - * against the same key. Used in the DirectExchange. - */ -class Index -{ - private ConcurrentMap<AMQShortString, ArrayList<AMQQueue>> _index - = new ConcurrentHashMap<AMQShortString, ArrayList<AMQQueue>>(); - private ConcurrentMap<String, ArrayList<AMQQueue>> _stringIndex - = new ConcurrentHashMap<String, ArrayList<AMQQueue>>(); - - - synchronized boolean add(AMQShortString key, AMQQueue queue) - { - ArrayList<AMQQueue> queues = _index.get(key); - if(queues == null) - { - queues = new ArrayList<AMQQueue>(); - } - else - { - queues = new ArrayList<AMQQueue>(queues); - } - - //next call is atomic, so there is no race to create the list - _index.put(key, queues); - _stringIndex.put(key.toString(), queues); - - if(queues.contains(queue)) - { - return false; - } - else - { - return queues.add(queue); - } - } - - - - synchronized boolean remove(AMQShortString key, AMQQueue queue) - { - ArrayList<AMQQueue> queues = _index.get(key); - if (queues != null) - { - queues = new ArrayList<AMQQueue>(queues); - boolean removed = queues.remove(queue); - if(removed) - { - if (queues.size() == 0) - { - _index.remove(key); - _stringIndex.remove(key.toString()); - } - else - { - _index.put(key, queues); - _stringIndex.put(key.toString(), queues); - } - } - return removed; - } - return false; - } - - ArrayList<AMQQueue> get(AMQShortString key) - { - return _index.get(key); - } - - ArrayList<AMQQueue> get(String key) - { - return _stringIndex.get(key); - } - - - Map<AMQShortString, List<AMQQueue>> getBindingsMap() - { - return new HashMap<AMQShortString, List<AMQQueue>>(_index); - } -} diff --git a/java/broker/src/main/java/org/apache/qpid/server/exchange/TopicExchange.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/TopicExchange.java index d5ca5a8a81..14f15dd92c 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/exchange/TopicExchange.java +++ b/java/broker/src/main/java/org/apache/qpid/server/exchange/TopicExchange.java @@ -21,32 +21,21 @@ package org.apache.qpid.server.exchange; import org.apache.log4j.Logger; + import org.apache.qpid.AMQException; +import org.apache.qpid.AMQInvalidArgumentException; import org.apache.qpid.common.AMQPFilterTypes; -import org.apache.qpid.management.common.mbeans.annotations.MBeanConstructor; -import org.apache.qpid.management.common.mbeans.annotations.MBeanDescription; -import org.apache.qpid.protocol.AMQConstant; import org.apache.qpid.exchange.ExchangeDefaults; import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.framing.FieldTable; -import org.apache.qpid.framing.AMQShortStringTokenizer; import org.apache.qpid.server.queue.AMQQueue; +import org.apache.qpid.server.queue.BaseQueue; import org.apache.qpid.server.virtualhost.VirtualHost; -import org.apache.qpid.server.exchange.topic.TopicParser; -import org.apache.qpid.server.exchange.topic.TopicMatcherResult; -import org.apache.qpid.server.filter.MessageFilter; +import org.apache.qpid.server.exchange.topic.*; import org.apache.qpid.server.filter.JMSSelectorFilter; import org.apache.qpid.server.message.InboundMessage; -import org.apache.qpid.server.logging.actors.CurrentActor; -import org.apache.qpid.server.logging.actors.ManagementActor; import javax.management.JMException; -import javax.management.MBeanException; -import javax.management.openmbean.CompositeData; -import javax.management.openmbean.CompositeDataSupport; -import javax.management.openmbean.OpenDataException; -import javax.management.openmbean.TabularData; -import javax.management.openmbean.TabularDataSupport; import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.lang.ref.WeakReference; @@ -87,314 +76,45 @@ public class TopicExchange extends AbstractExchange private static final Logger _logger = Logger.getLogger(TopicExchange.class); -/* - private final ConcurrentHashMap<AMQShortString, List<AMQQueue>> _bindingKey2queues = - new ConcurrentHashMap<AMQShortString, List<AMQQueue>>(); - private final ConcurrentHashMap<AMQShortString, List<AMQQueue>> _simpleBindingKey2queues = - new ConcurrentHashMap<AMQShortString, List<AMQQueue>>(); - private final ConcurrentHashMap<AMQShortString, List<AMQQueue>> _wildCardBindingKey2queues = - new ConcurrentHashMap<AMQShortString, List<AMQQueue>>(); -*/ - // private ConcurrentHashMap<AMQShortString, AMQQueue> _routingKey2queue = new ConcurrentHashMap<AMQShortString, AMQQueue>(); - private static final byte TOPIC_SEPARATOR = (byte)'.'; - private static final AMQShortString TOPIC_SEPARATOR_AS_SHORTSTRING = new AMQShortString("."); - private static final AMQShortString AMQP_STAR_TOKEN = new AMQShortString("*"); - private static final AMQShortString AMQP_HASH_TOKEN = new AMQShortString("#"); - - private static final byte HASH_BYTE = (byte)'#'; - private static final byte STAR_BYTE = (byte)'*'; + private final TopicParser _parser = new TopicParser(); private final Map<AMQShortString, TopicExchangeResult> _topicExchangeResults = new ConcurrentHashMap<AMQShortString, TopicExchangeResult>(); - private final Map<Binding, FieldTable> _bindings = new HashMap<Binding, FieldTable>(); + private final Map<TopicBinding, FieldTable> _bindings = new HashMap<TopicBinding, FieldTable>(); private final Map<String, WeakReference<JMSSelectorFilter>> _selectorCache = new WeakHashMap<String, WeakReference<JMSSelectorFilter>>(); - public static class Binding + public TopicExchange() { - private final AMQShortString _bindingKey; - private final AMQQueue _queue; - private final FieldTable _args; - - public Binding(AMQShortString bindingKey, AMQQueue queue, FieldTable args) - { - _bindingKey = bindingKey; - _queue = queue; - _args = args; - } - - public AMQShortString getBindingKey() - { - return _bindingKey; - } - - public AMQQueue getQueue() - { - return _queue; - } - - public int hashCode() - { - return (_bindingKey == null ? 1 : _bindingKey.hashCode())*31 +_queue.hashCode(); - } - - public boolean equals(Object o) - { - if(this == o) - { - return true; - } - if(o instanceof Binding) - { - Binding other = (Binding) o; - return (_queue == other._queue) - && ((_bindingKey == null) ? other._bindingKey == null : _bindingKey.equals(other._bindingKey)); - } - return false; - } - } - - - - private final class TopicExchangeResult implements TopicMatcherResult - { - private final Map<AMQQueue, Integer> _unfilteredQueues = new ConcurrentHashMap<AMQQueue, Integer>(); - private final ConcurrentHashMap<AMQQueue, Map<MessageFilter,Integer>> _filteredQueues = new ConcurrentHashMap<AMQQueue, Map<MessageFilter, Integer>>(); - - public void addUnfilteredQueue(AMQQueue queue) - { - Integer instances = _unfilteredQueues.get(queue); - if(instances == null) - { - _unfilteredQueues.put(queue, 1); - } - else - { - _unfilteredQueues.put(queue, instances + 1); - } - } - - public void removeUnfilteredQueue(AMQQueue queue) - { - Integer instances = _unfilteredQueues.get(queue); - if(instances == 1) - { - _unfilteredQueues.remove(queue); - } - else - { - _unfilteredQueues.put(queue,instances - 1); - } - - } - - - public void addFilteredQueue(AMQQueue queue, MessageFilter filter) - { - Map<MessageFilter,Integer> filters = _filteredQueues.get(queue); - if(filters == null) - { - filters = new ConcurrentHashMap<MessageFilter,Integer>(); - _filteredQueues.put(queue, filters); - } - Integer instances = filters.get(filter); - if(instances == null) - { - filters.put(filter,1); - } - else - { - filters.put(filter, instances + 1); - } - - } - - public void removeFilteredQueue(AMQQueue queue, MessageFilter filter) - { - Map<MessageFilter,Integer> filters = _filteredQueues.get(queue); - if(filters != null) - { - Integer instances = filters.get(filter); - if(instances != null) - { - if(instances == 1) - { - filters.remove(filter); - if(filters.isEmpty()) - { - _filteredQueues.remove(queue); - } - } - else - { - filters.put(filter, instances - 1); - } - } - - } - - } - - public void replaceQueueFilter(AMQQueue queue, - MessageFilter oldFilter, - MessageFilter newFilter) - { - Map<MessageFilter,Integer> filters = _filteredQueues.get(queue); - Map<MessageFilter,Integer> newFilters = new ConcurrentHashMap<MessageFilter,Integer>(filters); - Integer oldFilterInstances = filters.get(oldFilter); - if(oldFilterInstances == 1) - { - newFilters.remove(oldFilter); - } - else - { - newFilters.put(oldFilter, oldFilterInstances-1); - } - Integer newFilterInstances = filters.get(newFilter); - if(newFilterInstances == null) - { - newFilters.put(newFilter, 1); - } - else - { - newFilters.put(newFilter, newFilterInstances+1); - } - _filteredQueues.put(queue,newFilters); - } - - public Collection<AMQQueue> processMessage(InboundMessage msg, Collection<AMQQueue> queues) - { - if(queues == null) - { - if(_filteredQueues.isEmpty()) - { - return new ArrayList<AMQQueue>(_unfilteredQueues.keySet()); - } - else - { - queues = new HashSet<AMQQueue>(); - } - } - else if(!(queues instanceof Set)) - { - queues = new HashSet<AMQQueue>(queues); - } - - queues.addAll(_unfilteredQueues.keySet()); - if(!_filteredQueues.isEmpty()) - { - for(Map.Entry<AMQQueue, Map<MessageFilter, Integer>> entry : _filteredQueues.entrySet()) - { - if(!queues.contains(entry.getKey())) - { - for(MessageFilter filter : entry.getValue().keySet()) - { - if(filter.matches(msg)) - { - queues.add(entry.getKey()); - } - } - } - } - } - return queues; - } - + super(TYPE); } - - /** TopicExchangeMBean class implements the management interface for the Topic exchanges. */ - @MBeanDescription("Management Bean for Topic Exchange") - private final class TopicExchangeMBean extends ExchangeMBean + public synchronized void registerQueue(String rKey, AMQQueue queue, Map<String,Object> args) { - @MBeanConstructor("Creates an MBean for AMQ topic exchange") - public TopicExchangeMBean() throws JMException + try { - super(); - _exchangeType = "topic"; - init(); + registerQueue(new AMQShortString(rKey), queue, FieldTable.convertToFieldTable(args)); } - - /** returns exchange bindings in tabular form */ - public TabularData bindings() throws OpenDataException + catch (AMQInvalidArgumentException e) { - _bindingList = new TabularDataSupport(_bindinglistDataType); - Map<String, List<String>> bindingData = new HashMap<String, List<String>>(); - for (Binding binding : _bindings.keySet()) - { - String key = binding.getBindingKey().toString(); - List<String> queueNames = bindingData.get(key); - if(queueNames == null) - { - queueNames = new ArrayList<String>(); - bindingData.put(key, queueNames); - } - queueNames.add(binding.getQueue().getName().toString()); - - } - for(Map.Entry<String, List<String>> entry : bindingData.entrySet()) - { - Object[] bindingItemValues = {entry.getKey(), entry.getValue().toArray(new String[entry.getValue().size()]) }; - CompositeData bindingCompositeData = new CompositeDataSupport(_bindingDataType, COMPOSITE_ITEM_NAMES, bindingItemValues); - _bindingList.put(bindingCompositeData); - } - - return _bindingList; + throw new RuntimeException(e); } - - public void createNewBinding(String queueName, String binding) throws JMException - { - AMQQueue queue = getQueueRegistry().getQueue(new AMQShortString(queueName)); - if (queue == null) - { - throw new JMException("Queue \"" + queueName + "\" is not registered with the exchange."); - } - - CurrentActor.set(new ManagementActor(_logActor.getRootMessageLogger())); - try - { - queue.bind(TopicExchange.this, new AMQShortString(binding), null); - } - catch (AMQException ex) - { - throw new MBeanException(ex); - } - finally - { - CurrentActor.remove(); - } - } - - } // End of MBean class - - public AMQShortString getType() - { - return ExchangeDefaults.TOPIC_EXCHANGE_CLASS; } - public synchronized void registerQueue(AMQShortString rKey, AMQQueue queue, FieldTable args) throws AMQException + public synchronized void registerQueue(AMQShortString rKey, AMQQueue queue, FieldTable args) throws AMQInvalidArgumentException { assert queue != null; assert rKey != null; - _logger.debug("Registering queue " + queue.getName() + " with routing key " + rKey); + _logger.debug("Registering queue " + queue.getNameShortString() + " with routing key " + rKey); - AMQShortString routingKey; + AMQShortString routingKey = TopicNormalizer.normalize(rKey); - if(rKey.contains(HASH_BYTE) || rKey.contains(STAR_BYTE)) - { - routingKey = normalize(rKey); - } - else - { - routingKey = rKey; - } - - Binding binding = new Binding(rKey, queue, args); + TopicBinding binding = new TopicBinding(rKey, queue, args); if(_bindings.containsKey(binding)) { @@ -463,8 +183,7 @@ public class TopicExchange extends AbstractExchange } - private JMSSelectorFilter createSelectorFilter(final FieldTable args) - throws AMQException + private JMSSelectorFilter createSelectorFilter(final FieldTable args) throws AMQInvalidArgumentException { final String selectorString = args.getString(AMQPFilterTypes.JMS_SELECTOR.getValue()); @@ -484,58 +203,7 @@ public class TopicExchange extends AbstractExchange return args != null && args.containsKey(AMQPFilterTypes.JMS_SELECTOR.getValue()) && args.getString(AMQPFilterTypes.JMS_SELECTOR.getValue()).trim().length() != 0; } - private AMQShortString normalize(AMQShortString routingKey) - { - if(routingKey == null) - { - routingKey = AMQShortString.EMPTY_STRING; - } - - AMQShortStringTokenizer routingTokens = routingKey.tokenize(TOPIC_SEPARATOR); - - List<AMQShortString> subscriptionList = new ArrayList<AMQShortString>(); - - while (routingTokens.hasMoreTokens()) - { - subscriptionList.add(routingTokens.nextToken()); - } - - int size = subscriptionList.size(); - - for (int index = 0; index < size; index++) - { - // if there are more levels - if ((index + 1) < size) - { - if (subscriptionList.get(index).equals(AMQP_HASH_TOKEN)) - { - if (subscriptionList.get(index + 1).equals(AMQP_HASH_TOKEN)) - { - // we don't need #.# delete this one - subscriptionList.remove(index); - size--; - // redo this normalisation - index--; - } - - if (subscriptionList.get(index + 1).equals(AMQP_STAR_TOKEN)) - { - // we don't want #.* swap to *.# - // remove it and put it in at index + 1 - subscriptionList.add(index + 1, subscriptionList.remove(index)); - } - } - } // if we have more levels - } - - - - AMQShortString normalizedString = AMQShortString.join(subscriptionList, TOPIC_SEPARATOR_AS_SHORTSTRING); - - return normalizedString; - } - - public ArrayList<AMQQueue> route(InboundMessage payload) + public ArrayList<BaseQueue> doRoute(InboundMessage payload) { final AMQShortString routingKey = payload.getRoutingKey() == null @@ -544,7 +212,7 @@ public class TopicExchange extends AbstractExchange // The copy here is unfortunate, but not too bad relevant to the amount of // things created and copied in getMatchedQueues - ArrayList<AMQQueue> queues = new ArrayList<AMQQueue>(); + ArrayList<BaseQueue> queues = new ArrayList<BaseQueue>(); queues.addAll(getMatchedQueues(payload, routingKey)); if(queues == null || queues.isEmpty()) @@ -558,7 +226,7 @@ public class TopicExchange extends AbstractExchange public boolean isBound(AMQShortString routingKey, FieldTable arguments, AMQQueue queue) { - Binding binding = new Binding(routingKey, queue, arguments); + TopicBinding binding = new TopicBinding(routingKey, queue, arguments); if (arguments == null) { return _bindings.containsKey(binding); @@ -585,7 +253,7 @@ public class TopicExchange extends AbstractExchange public boolean isBound(AMQShortString routingKey) { - for(Binding b : _bindings.keySet()) + for(TopicBinding b : _bindings.keySet()) { if(b.getBindingKey().equals(routingKey)) { @@ -598,7 +266,7 @@ public class TopicExchange extends AbstractExchange public boolean isBound(AMQQueue queue) { - for(Binding b : _bindings.keySet()) + for(TopicBinding b : _bindings.keySet()) { if(b.getQueue().equals(queue)) { @@ -614,37 +282,45 @@ public class TopicExchange extends AbstractExchange return !_bindings.isEmpty(); } - public synchronized void deregisterQueue(AMQShortString rKey, AMQQueue queue, FieldTable args) throws AMQException - { - assert queue != null; - assert rKey != null; - - Binding binding = new Binding(rKey, queue, args); - - if (!_bindings.containsKey(binding)) - { - throw new AMQException(AMQConstant.NOT_FOUND, "Queue " + queue.getName() + " was not registered with exchange " + this.getName() - + " with routing key " + rKey + "."); - } + public void deregisterQueue(String rKey, AMQQueue queue, Map<String, Object> args) + { + removeBinding(new TopicBinding(new AMQShortString(rKey), queue, FieldTable.convertToFieldTable(args))); + } - FieldTable bindingArgs = _bindings.remove(binding); - AMQShortString bindingKey = normalize(rKey); - TopicExchangeResult result = _topicExchangeResults.get(bindingKey); - if(argumentsContainSelector(bindingArgs)) + private boolean removeBinding(final TopicBinding binding) + { + if(_bindings.containsKey(binding)) { - result.removeFilteredQueue(queue, createSelectorFilter(bindingArgs)); + FieldTable bindingArgs = _bindings.remove(binding); + AMQShortString bindingKey = TopicNormalizer.normalize(binding.getBindingKey()); + TopicExchangeResult result = _topicExchangeResults.get(bindingKey); + if(argumentsContainSelector(bindingArgs)) + { + try + { + result.removeFilteredQueue(binding.getQueue(), createSelectorFilter(bindingArgs)); + } + catch (AMQInvalidArgumentException e) + { + return false; + } + } + else + { + result.removeUnfilteredQueue(binding.getQueue()); + } + return true; } else { - result.removeUnfilteredQueue(queue); + return false; } - } - protected ExchangeMBean createMBean() throws JMException + protected AbstractExchangeMBean createMBean() throws JMException { - return new TopicExchangeMBean(); + return new TopicExchangeMBean(this); } public Logger getLogger() @@ -673,4 +349,15 @@ public class TopicExchange extends AbstractExchange } + + protected void onBind(final org.apache.qpid.server.binding.Binding binding) + { + registerQueue(binding.getBindingKey(),binding.getQueue(),binding.getArguments()); + } + + protected void onUnbind(final org.apache.qpid.server.binding.Binding binding) + { + deregisterQueue(binding.getBindingKey(),binding.getQueue(),binding.getArguments()); + } + } diff --git a/java/broker/src/main/java/org/apache/qpid/server/exchange/TopicExchangeMBean.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/TopicExchangeMBean.java new file mode 100644 index 0000000000..de39822ff7 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/exchange/TopicExchangeMBean.java @@ -0,0 +1,74 @@ +/* + * + * 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.exchange; + +import org.apache.qpid.management.common.mbeans.annotations.MBeanDescription; +import org.apache.qpid.management.common.mbeans.annotations.MBeanConstructor; +import org.apache.qpid.server.binding.Binding; + +import javax.management.JMException; +import javax.management.openmbean.*; +import java.util.List; +import java.util.Map; +import java.util.HashMap; +import java.util.ArrayList; + +/** TopicExchangeMBean class implements the management interface for the Topic exchanges. */ +@MBeanDescription("Management Bean for Topic Exchange") +final class TopicExchangeMBean extends AbstractExchangeMBean<TopicExchange> +{ + private TopicExchange _topicExchange; + + @MBeanConstructor("Creates an MBean for AMQ topic exchange") + public TopicExchangeMBean(final TopicExchange topicExchange) throws JMException + { + super(topicExchange); + init(); + } + + /** returns exchange bindings in tabular form */ + public TabularData bindings() throws OpenDataException + { + TabularDataSupport bindingList = new TabularDataSupport(_bindinglistDataType); + Map<String, List<String>> bindingData = new HashMap<String, List<String>>(); + for (Binding binding : getExchange().getBindings()) + { + String key = binding.getBindingKey(); + List<String> queueNames = bindingData.get(key); + if(queueNames == null) + { + queueNames = new ArrayList<String>(); + bindingData.put(key, queueNames); + } + queueNames.add(binding.getQueue().getNameShortString().toString()); + + } + for(Map.Entry<String, List<String>> entry : bindingData.entrySet()) + { + Object[] bindingItemValues = {entry.getKey(), entry.getValue().toArray(new String[entry.getValue().size()]) }; + CompositeData bindingCompositeData = new CompositeDataSupport(_bindingDataType, COMPOSITE_ITEM_NAMES, bindingItemValues); + bindingList.put(bindingCompositeData); + } + + return bindingList; + } + +} // End of MBean class diff --git a/java/broker/src/main/java/org/apache/qpid/server/exchange/topic/TopicBinding.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/topic/TopicBinding.java new file mode 100644 index 0000000000..c6383a886e --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/exchange/topic/TopicBinding.java @@ -0,0 +1,70 @@ +/* + * + * 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.exchange.topic; + +import org.apache.qpid.framing.AMQShortString; +import org.apache.qpid.framing.FieldTable; +import org.apache.qpid.server.queue.AMQQueue; +import org.apache.qpid.server.exchange.TopicExchange; + +public class TopicBinding +{ + private final AMQShortString _bindingKey; + private final AMQQueue _queue; + private final FieldTable _args; + + public TopicBinding(AMQShortString bindingKey, AMQQueue queue, FieldTable args) + { + _bindingKey = bindingKey; + _queue = queue; + _args = args; + } + + public AMQShortString getBindingKey() + { + return _bindingKey; + } + + public AMQQueue getQueue() + { + return _queue; + } + + public int hashCode() + { + return (_bindingKey == null ? 1 : _bindingKey.hashCode())*31 +_queue.hashCode(); + } + + public boolean equals(Object o) + { + if(this == o) + { + return true; + } + if(o instanceof TopicBinding) + { + TopicBinding other = (TopicBinding) o; + return (_queue == other._queue) + && ((_bindingKey == null) ? other._bindingKey == null : _bindingKey.equals(other._bindingKey)); + } + return false; + } +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/exchange/topic/TopicExchangeResult.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/topic/TopicExchangeResult.java new file mode 100644 index 0000000000..d9a779802f --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/exchange/topic/TopicExchangeResult.java @@ -0,0 +1,179 @@ +/* + * + * 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.exchange.topic; + +import org.apache.qpid.server.queue.AMQQueue; +import org.apache.qpid.server.filter.MessageFilter; +import org.apache.qpid.server.message.InboundMessage; + +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; + +public final class TopicExchangeResult implements TopicMatcherResult +{ + private final Map<AMQQueue, Integer> _unfilteredQueues = new ConcurrentHashMap<AMQQueue, Integer>(); + private final ConcurrentHashMap<AMQQueue, Map<MessageFilter,Integer>> _filteredQueues = new ConcurrentHashMap<AMQQueue, Map<MessageFilter, Integer>>(); + + public void addUnfilteredQueue(AMQQueue queue) + { + Integer instances = _unfilteredQueues.get(queue); + if(instances == null) + { + _unfilteredQueues.put(queue, 1); + } + else + { + _unfilteredQueues.put(queue, instances + 1); + } + } + + public void removeUnfilteredQueue(AMQQueue queue) + { + Integer instances = _unfilteredQueues.get(queue); + if(instances == 1) + { + _unfilteredQueues.remove(queue); + } + else + { + _unfilteredQueues.put(queue,instances - 1); + } + + } + + public Collection<AMQQueue> getUnfilteredQueues() + { + return _unfilteredQueues.keySet(); + } + + + public void addFilteredQueue(AMQQueue queue, MessageFilter filter) + { + Map<MessageFilter,Integer> filters = _filteredQueues.get(queue); + if(filters == null) + { + filters = new ConcurrentHashMap<MessageFilter,Integer>(); + _filteredQueues.put(queue, filters); + } + Integer instances = filters.get(filter); + if(instances == null) + { + filters.put(filter,1); + } + else + { + filters.put(filter, instances + 1); + } + + } + + public void removeFilteredQueue(AMQQueue queue, MessageFilter filter) + { + Map<MessageFilter,Integer> filters = _filteredQueues.get(queue); + if(filters != null) + { + Integer instances = filters.get(filter); + if(instances != null) + { + if(instances == 1) + { + filters.remove(filter); + if(filters.isEmpty()) + { + _filteredQueues.remove(queue); + } + } + else + { + filters.put(filter, instances - 1); + } + } + + } + + } + + public void replaceQueueFilter(AMQQueue queue, + MessageFilter oldFilter, + MessageFilter newFilter) + { + Map<MessageFilter,Integer> filters = _filteredQueues.get(queue); + Map<MessageFilter,Integer> newFilters = new ConcurrentHashMap<MessageFilter,Integer>(filters); + Integer oldFilterInstances = filters.get(oldFilter); + if(oldFilterInstances == 1) + { + newFilters.remove(oldFilter); + } + else + { + newFilters.put(oldFilter, oldFilterInstances-1); + } + Integer newFilterInstances = filters.get(newFilter); + if(newFilterInstances == null) + { + newFilters.put(newFilter, 1); + } + else + { + newFilters.put(newFilter, newFilterInstances+1); + } + _filteredQueues.put(queue,newFilters); + } + + public Collection<AMQQueue> processMessage(InboundMessage msg, Collection<AMQQueue> queues) + { + if(queues == null) + { + if(_filteredQueues.isEmpty()) + { + return new ArrayList<AMQQueue>(_unfilteredQueues.keySet()); + } + else + { + queues = new HashSet<AMQQueue>(); + } + } + else if(!(queues instanceof Set)) + { + queues = new HashSet<AMQQueue>(queues); + } + + queues.addAll(_unfilteredQueues.keySet()); + if(!_filteredQueues.isEmpty()) + { + for(Map.Entry<AMQQueue, Map<MessageFilter, Integer>> entry : _filteredQueues.entrySet()) + { + if(!queues.contains(entry.getKey())) + { + for(MessageFilter filter : entry.getValue().keySet()) + { + if(filter.matches(msg)) + { + queues.add(entry.getKey()); + } + } + } + } + } + return queues; + } + +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/exchange/topic/TopicNormalizer.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/topic/TopicNormalizer.java new file mode 100644 index 0000000000..7e7cb6c0ae --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/exchange/topic/TopicNormalizer.java @@ -0,0 +1,96 @@ +/* + * + * 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.exchange.topic; + +import org.apache.qpid.framing.AMQShortString; +import org.apache.qpid.framing.AMQShortStringTokenizer; +import org.apache.qpid.server.exchange.TopicExchange; + +import java.util.List; +import java.util.ArrayList; + +public class TopicNormalizer +{ + private static final byte TOPIC_SEPARATOR = (byte)'.'; + private static final byte HASH_BYTE = (byte)'#'; + private static final byte STAR_BYTE = (byte)'*'; + + private static final AMQShortString TOPIC_SEPARATOR_AS_SHORTSTRING = new AMQShortString("."); + private static final AMQShortString AMQP_STAR_TOKEN = new AMQShortString("*"); + private static final AMQShortString AMQP_HASH_TOKEN = new AMQShortString("#"); + + public static AMQShortString normalize(AMQShortString routingKey) + { + if(routingKey == null) + { + return AMQShortString.EMPTY_STRING; + } + else if(!(routingKey.contains(HASH_BYTE) || routingKey.contains(STAR_BYTE))) + { + return routingKey; + } + else + { + AMQShortStringTokenizer routingTokens = routingKey.tokenize(TOPIC_SEPARATOR); + + List<AMQShortString> subscriptionList = new ArrayList<AMQShortString>(); + + while (routingTokens.hasMoreTokens()) + { + subscriptionList.add(routingTokens.nextToken()); + } + + int size = subscriptionList.size(); + + for (int index = 0; index < size; index++) + { + // if there are more levels + if ((index + 1) < size) + { + if (subscriptionList.get(index).equals(AMQP_HASH_TOKEN)) + { + if (subscriptionList.get(index + 1).equals(AMQP_HASH_TOKEN)) + { + // we don't need #.# delete this one + subscriptionList.remove(index); + size--; + // redo this normalisation + index--; + } + + if (subscriptionList.get(index + 1).equals(AMQP_STAR_TOKEN)) + { + // we don't want #.* swap to *.# + // remove it and put it in at index + 1 + subscriptionList.add(index + 1, subscriptionList.remove(index)); + } + } + } // if we have more levels + } + + + + AMQShortString normalizedString = AMQShortString.join(subscriptionList, TOPIC_SEPARATOR_AS_SHORTSTRING); + + return normalizedString; + } + } +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/federation/Bridge.java b/java/broker/src/main/java/org/apache/qpid/server/federation/Bridge.java new file mode 100644 index 0000000000..c97d71dc39 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/federation/Bridge.java @@ -0,0 +1,807 @@ +/* + * + * 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.federation; + +import org.apache.qpid.AMQException; +import org.apache.qpid.server.binding.Binding; +import org.apache.qpid.server.configuration.BridgeConfig; +import org.apache.qpid.server.configuration.BridgeConfigType; +import org.apache.qpid.server.configuration.ConfiguredObject; +import org.apache.qpid.server.exchange.Exchange; +import org.apache.qpid.server.exchange.ExchangeRegistry; +import org.apache.qpid.server.flow.FlowCreditManager_0_10; +import org.apache.qpid.server.flow.WindowCreditManager; +import org.apache.qpid.server.message.MessageMetaData_0_10; +import org.apache.qpid.server.message.MessageTransferMessage; +import org.apache.qpid.server.message.ServerMessage; +import org.apache.qpid.server.queue.AMQQueue; +import org.apache.qpid.server.queue.AMQQueueFactory; +import org.apache.qpid.server.queue.BaseQueue; +import org.apache.qpid.server.queue.QueueRegistry; +import org.apache.qpid.server.store.MessageStore; +import org.apache.qpid.server.store.StoredMessage; +import org.apache.qpid.server.subscription.Subscription_0_10; +import org.apache.qpid.server.transport.ServerSession; +import org.apache.qpid.server.txn.AutoCommitTransaction; +import org.apache.qpid.server.txn.ServerTransaction; +import org.apache.qpid.server.virtualhost.VirtualHost; +import org.apache.qpid.transport.DeliveryProperties; +import org.apache.qpid.transport.MessageAcceptMode; +import org.apache.qpid.transport.MessageAcquireMode; +import org.apache.qpid.transport.MessageCreditUnit; +import org.apache.qpid.transport.MessageFlowMode; +import org.apache.qpid.transport.MessageReject; +import org.apache.qpid.transport.MessageRejectCode; +import org.apache.qpid.transport.MessageTransfer; +import org.apache.qpid.transport.Option; +import org.apache.qpid.transport.RangeSet; +import org.apache.qpid.transport.Session; +import org.apache.qpid.transport.SessionException; +import org.apache.qpid.transport.SessionListener; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + +public class Bridge implements BridgeConfig +{ + private final boolean _durable; + private final boolean _dynamic; + private final boolean _queueBridge; + private final boolean _localSource; + private final String _source; + private final String _destination; + private final String _key; + private final String _tag; + private final String _excludes; + private final BrokerLink _link; + private UUID _id; + private long _createTime = System.currentTimeMillis(); + + private Session _session; + + private BridgeImpl _delegate; + + private final int _bridgeNo; + private AutoCommitTransaction _transaction; + + public Bridge(final BrokerLink brokerLink, + final int bridgeNo, + final boolean durable, + final boolean dynamic, + final boolean srcIsQueue, + final boolean srcIsLocal, + final String src, + final String dest, + final String key, + final String tag, + final String excludes) + { + _link = brokerLink; + _bridgeNo = bridgeNo; + _durable = durable; + _dynamic = dynamic; + _queueBridge = srcIsQueue; + _localSource = srcIsLocal; + _source = src; + _destination = dest; + _key = key; + _tag = tag; + _excludes = excludes; + _id = brokerLink.getConfigStore().createId(); + + _transaction = new AutoCommitTransaction(getVirtualHost().getMessageStore()); + + if(dynamic) + { + if(srcIsLocal) + { + // TODO + } + else + { + if(srcIsQueue) + { + // TODO + } + else + { + _delegate = new DynamicExchangeBridge(); + } + } + } + else + { + if(srcIsLocal) + { + if(srcIsQueue) + { + _delegate = new StaticQueuePushBridge(); + } + else + { + _delegate = new StaticExchangePushBridge(); + } + } + else + { + if(srcIsQueue) + { + _delegate = new StaticQueuePullBridge(); + } + else + { + _delegate = new StaticExchangePullBridge(); + } + } + } + } + + public UUID getId() + { + return _id; + } + + public BridgeConfigType getConfigType() + { + return BridgeConfigType.getInstance(); + } + + public ConfiguredObject getParent() + { + return getLink(); + } + + public boolean isDurable() + { + return _durable; + } + + public boolean isDynamic() + { + return _dynamic; + } + + public boolean isQueueBridge() + { + return _queueBridge; + } + + public boolean isLocalSource() + { + return _localSource; + } + + public String getSource() + { + return _source; + } + + public String getDestination() + { + return _destination; + } + + public String getKey() + { + return _key; + } + + public String getTag() + { + return _tag; + } + + public String getExcludes() + { + return _excludes; + } + + public BrokerLink getLink() + { + return _link; + } + + public Integer getChannelId() + { + return (_session == null) ? 0 : _session.getChannel(); + } + + public int getAckBatching() + { + return 0; + } + + public long getCreateTime() + { + return _createTime; + } + + @Override + public boolean equals(final Object o) + { + if (this == o) + { + return true; + } + if (o == null || getClass() != o.getClass()) + { + return false; + } + + final Bridge bridge = (Bridge) o; + + if (_durable != bridge._durable) + { + return false; + } + if (_dynamic != bridge._dynamic) + { + return false; + } + if (_localSource != bridge._localSource) + { + return false; + } + if (_queueBridge != bridge._queueBridge) + { + return false; + } + if (_destination != null ? !_destination.equals(bridge._destination) : bridge._destination != null) + { + return false; + } + if (_excludes != null ? !_excludes.equals(bridge._excludes) : bridge._excludes != null) + { + return false; + } + if (_key != null ? !_key.equals(bridge._key) : bridge._key != null) + { + return false; + } + if (_source != null ? !_source.equals(bridge._source) : bridge._source != null) + { + return false; + } + if (_tag != null ? !_tag.equals(bridge._tag) : bridge._tag != null) + { + return false; + } + + return true; + } + + @Override + public int hashCode() + { + int result = (_durable ? 1 : 0); + result = 31 * result + (_dynamic ? 1 : 0); + result = 31 * result + (_queueBridge ? 1 : 0); + result = 31 * result + (_localSource ? 1 : 0); + result = 31 * result + (_source != null ? _source.hashCode() : 0); + result = 31 * result + (_destination != null ? _destination.hashCode() : 0); + result = 31 * result + (_key != null ? _key.hashCode() : 0); + result = 31 * result + (_tag != null ? _tag.hashCode() : 0); + result = 31 * result + (_excludes != null ? _excludes.hashCode() : 0); + return result; + } + + public void setSession(final Session session) + { + _session = session; + _delegate.setSession(session); + } + + private long getMessageWindowSize() + { + return 10l; + } + + + VirtualHost getVirtualHost() + { + return _link.getVirtualHost(); + } + + public void close() + { + // TODO + _delegate.close(); + _session = null; + } + + + private interface BridgeImpl + { + void setSession(Session session); + + void close(); + } + + private abstract class AbstractPullBridge implements BridgeImpl, SessionListener + { + public final void setSession(final Session session) + { + session.setSessionListener(this); + onSession(); + + } + + abstract void onSession(); + + + + public void message(final Session ssn, final MessageTransfer xfr) + { + ExchangeRegistry exchangeRegistry = getVirtualHost().getExchangeRegistry(); + + Exchange exchange = exchangeRegistry.getExchange(_destination); + + // TODO - deal with exchange not existing + + DeliveryProperties delvProps = null; + if(xfr.getHeader() != null && (delvProps = xfr.getHeader().get(DeliveryProperties.class)) != null && delvProps.hasTtl() && !delvProps.hasExpiration()) + { + delvProps.setExpiration(System.currentTimeMillis() + delvProps.getTtl()); + } + + MessageMetaData_0_10 messageMetaData = new MessageMetaData_0_10(xfr); + final MessageStore store = getVirtualHost().getMessageStore(); + StoredMessage<MessageMetaData_0_10> storeMessage = store.addMessage(messageMetaData); + storeMessage.addContent(0,xfr.getBody()); + storeMessage.flushToStore(); + MessageTransferMessage message = new MessageTransferMessage(storeMessage, ((ServerSession)_session).getReference()); + + ArrayList<? extends BaseQueue> queues = exchange.route(message); + + + + if(queues != null && queues.size() != 0) + { + enqueue(message, queues); + } + else + { + if(delvProps == null || !delvProps.hasDiscardUnroutable() || !delvProps.getDiscardUnroutable()) + { + if(xfr.getAcceptMode() == MessageAcceptMode.EXPLICIT) + { + RangeSet rejects = new RangeSet(); + rejects.add(xfr.getId()); + MessageReject reject = new MessageReject(rejects, MessageRejectCode.UNROUTABLE, "Unroutable"); + ssn.invoke(reject); + } + else + { + Exchange alternate = exchange.getAlternateExchange(); + if(alternate != null) + { + queues = alternate.route(message); + if(queues != null && queues.size() != 0) + { + enqueue(message, queues); + } + else + { + //TODO - log the message discard + } + } + else + { + //TODO - log the message discard + } + + + } + } + + + } + + ssn.processed(xfr); + + } + + + private void enqueue(final ServerMessage message, final ArrayList<? extends BaseQueue> queues) + { + _transaction.enqueue(queues,message, new ServerTransaction.Action() + { + + BaseQueue[] _queues = queues.toArray(new BaseQueue[queues.size()]); + + public void postCommit() + { + for(int i = 0; i < _queues.length; i++) + { + try + { + _queues[i].enqueue(message); + } + catch (AMQException e) + { + // TODO + + throw new RuntimeException(e); + } + } + } + + public void onRollback() + { + // NO-OP + } + }); + + } + + public void exception(final Session session, final SessionException exception) + { + // TODO - Handle exceptions + } + + public void closed(final Session session) + { + // TODO - handle close + } + + public void opened(final Session session) + { + // this method never called + } + + public void resumed(final Session session) + { + // will never resume these sessions + } + + + + } + + private final class StaticExchangePullBridge extends AbstractPullBridge + { + private final String _tmpQueueName = "bridge_queue_" + _bridgeNo + "_" + _link.getFederationTag();; + + public void onSession() + { + + final HashMap<String, Object> options = new HashMap<String, Object>(); + options.put("qpid.trace.exclude", _link.getFederationTag()); + options.put("qpid.trace.id",_link.getRemoteFederationTag()); + _session.queueDeclare(_tmpQueueName,null, options, Option.AUTO_DELETE, Option.EXCLUSIVE); + _session.sync(); + // todo check exception + final Map<String,Object> bindingArgs = new HashMap<String,Object>(); + _session.exchangeBind(_tmpQueueName, _source, _key, bindingArgs); + _session.sync(); + // todo check exception + + final Map<String,Object> subscribeOptions = Collections.EMPTY_MAP; + final String subName = String.valueOf(_bridgeNo); + _session.messageSubscribe(_tmpQueueName, + subName,MessageAcceptMode.NONE,MessageAcquireMode.PRE_ACQUIRED,null,0l, subscribeOptions); + _session.sync(); + // todo check exception + + _session.messageSetFlowMode(subName,MessageFlowMode.WINDOW); + _session.messageFlow(subName, MessageCreditUnit.MESSAGE, getMessageWindowSize()); + _session.messageFlow(subName, MessageCreditUnit.BYTE, 0xFFFFFFFF); + + } + + public void close() + { + // TODO + } + } + + private final class StaticQueuePullBridge extends AbstractPullBridge + { + + public void onSession() + { + + final Map<String,Object> subscribeOptions = Collections.EMPTY_MAP; + final String subName = String.valueOf(_bridgeNo); + _session.messageSubscribe(_source, + subName,MessageAcceptMode.NONE,MessageAcquireMode.PRE_ACQUIRED,null,0l, subscribeOptions); + _session.sync(); + // todo check exception + + _session.messageSetFlowMode(subName,MessageFlowMode.WINDOW); + _session.messageFlow(subName, MessageCreditUnit.MESSAGE, getMessageWindowSize()); + _session.messageFlow(subName, MessageCreditUnit.BYTE, 0xFFFFFFFF); + + } + + public void close() + { + // TODO + } + } + + private final class DynamicExchangeBridge extends AbstractPullBridge implements Exchange.BindingListener + { + private final String _tmpQueueName = "bridge_queue_" + _bridgeNo + "_" + _link.getFederationTag(); + + private final ConcurrentMap<Binding,Binding> _bindings = new ConcurrentHashMap<Binding,Binding>(); + + + void onSession() + { + + + final HashMap<String, Object> options = new HashMap<String, Object>(); + options.put("qpid.trace.exclude", _link.getFederationTag()); + options.put("qpid.trace.id",_link.getRemoteFederationTag()); + _session.queueDeclare(_tmpQueueName,null, options, Option.AUTO_DELETE, Option.EXCLUSIVE); + _session.sync(); + // todo - check exception + + final Map<String,Object> subscribeOptions = Collections.EMPTY_MAP; + final String subName = String.valueOf(_bridgeNo); + _session.messageSubscribe(_tmpQueueName, + subName,MessageAcceptMode.NONE,MessageAcquireMode.PRE_ACQUIRED,null,0l, subscribeOptions); + _session.sync(); + // todo check exception + _session.messageSetFlowMode(subName,MessageFlowMode.WINDOW); + _session.messageFlow(subName, MessageCreditUnit.MESSAGE, getMessageWindowSize()); + _session.messageFlow(subName, MessageCreditUnit.BYTE, 0xFFFFFFFF); + _session.sync(); + // todo check exception + + + ExchangeRegistry exchangeRegistry = getVirtualHost().getExchangeRegistry(); + + Exchange exchange = exchangeRegistry.getExchange(_destination); + + // TODO - check null + + exchange.addBindingListener(this); + + Collection<Binding> bindings = exchange.getBindings(); + for(Binding binding : bindings) + { + propogateBinding(binding); + } + + } + + private void propogateBinding(final Binding binding) + { + if(_bindings.putIfAbsent(binding,binding)== null) + { + Map<String,Object> arguments = new HashMap<String,Object>(binding.getArguments()); + + if(arguments.get("qpid.fed.origin") == null) + { + arguments.put("qpid.fed.op",""); + arguments.put("qpid.fed.origin",_link.getFederationTag()); + arguments.put("qpid.fed.tags",_link.getFederationTag()); + } + else + { + String tags = (String) arguments.get("qpid.fed.tags"); + if(tags == null) + { + tags = _link.getFederationTag(); + } + else + { + if(Arrays.asList(tags.split(",")).contains(_link.getFederationTag())) + { + return; + } + tags += "," + _link.getFederationTag(); + } + arguments.put("qpid.fed.tags", tags); + } + + _session.exchangeBind(_tmpQueueName, _source, binding.getBindingKey(), arguments); + _session.sync(); + // TODO - check exception? + + } + } + + private void propogateBindingRemoval(final Binding binding) + { + if(_bindings.remove(binding) != null) + { + // TODO - this is wrong!!!! + _session.exchangeUnbind(_tmpQueueName, _source, binding.getBindingKey()); + } + } + + + public void bindingAdded(final Exchange exchange, final Binding binding) + { + propogateBinding(binding); + } + + public void bindingRemoved(final Exchange exchange, final Binding binding) + { + propogateBindingRemoval(binding); + } + + public void close() + { + // TODO + } + } + + private class StaticExchangePushBridge implements BridgeImpl, SessionListener + { + private final String _tmpQueueName = "bridge_queue_" + _bridgeNo + "_" + _link.getFederationTag(); + private AMQQueue _queue; + + public void setSession(final Session session) + { + session.setSessionListener(this); + + ExchangeRegistry exchangeRegistry = getVirtualHost().getExchangeRegistry(); + + Exchange exchange = exchangeRegistry.getExchange(_source); + + // TODO - Check null + + final HashMap<String, Object> options = new HashMap<String, Object>(); + options.put("qpid.trace.exclude", _link.getFederationTag()); + options.put("qpid.trace.id",_link.getRemoteFederationTag()); + + _queue = AMQQueueFactory.createAMQQueueImpl(_tmpQueueName, + isDurable(), + _link.getFederationTag(), + false, + getVirtualHost(), + options); + + FlowCreditManager_0_10 creditManager = new WindowCreditManager(0xFFFFFFFF,getMessageWindowSize()); + + Subscription_0_10 sub = new Subscription_0_10((ServerSession)session, + _destination, + MessageAcceptMode.NONE, + MessageAcquireMode.PRE_ACQUIRED, + MessageFlowMode.WINDOW, + creditManager, null); + + ((ServerSession)session).register(_destination, sub); + + try + { + _queue.registerSubscription(sub, true); + } + catch (AMQException e) + { + // TODO + throw new RuntimeException(e); + } + + getVirtualHost().getBindingFactory().addBinding(_key, _queue, exchange, Collections.EMPTY_MAP); + } + + public void close() + { + // TODO + } + + public void opened(final Session session) + { + // this method never called + } + + public void resumed(final Session session) + { + // this session will never be resumed + } + + public void message(final Session ssn, final MessageTransfer xfr) + { + // messages should not be sent ... should probably log error + } + + public void exception(final Session session, final SessionException exception) + { + // TODO + } + + public void closed(final Session session) + { + // TODO + } + } + + private class StaticQueuePushBridge implements BridgeImpl, SessionListener + { + private AMQQueue _queue; + + public void setSession(final Session session) + { + session.setSessionListener(this); + + QueueRegistry queueRegistry = getVirtualHost().getQueueRegistry(); + + _queue = queueRegistry.getQueue(_source); + + // TODO - null check + + FlowCreditManager_0_10 creditManager = new WindowCreditManager(0xFFFFFFFF,getMessageWindowSize()); + + Subscription_0_10 sub = new Subscription_0_10((ServerSession)session, + _destination, + MessageAcceptMode.NONE, + MessageAcquireMode.PRE_ACQUIRED, + MessageFlowMode.WINDOW, + creditManager, null); + + ((ServerSession)session).register(_destination, sub); + + try + { + _queue.registerSubscription(sub, false); + } + catch (AMQException e) + { + // TODO + throw new RuntimeException(e); + } + + } + + public void close() + { + // TODO + } + + public void opened(final Session session) + { + // never called + } + + public void resumed(final Session session) + { + // session will not resume + } + + public void message(final Session ssn, final MessageTransfer xfr) + { + // should never be called ... should probably log error + } + + public void exception(final Session session, final SessionException exception) + { + // TODO + } + + public void closed(final Session session) + { + // TODO + } + } + +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/federation/BrokerLink.java b/java/broker/src/main/java/org/apache/qpid/server/federation/BrokerLink.java new file mode 100644 index 0000000000..bb6fb9dcc3 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/federation/BrokerLink.java @@ -0,0 +1,497 @@ +/* + * + * 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.federation; + +import org.apache.qpid.server.configuration.ConfigStore; +import org.apache.qpid.server.configuration.ConfiguredObject; +import org.apache.qpid.server.configuration.ConnectionConfig; +import org.apache.qpid.server.configuration.ConnectionConfigType; +import org.apache.qpid.server.configuration.LinkConfig; +import org.apache.qpid.server.configuration.LinkConfigType; +import org.apache.qpid.server.transport.ServerSession; +import org.apache.qpid.server.virtualhost.VirtualHost; +import org.apache.qpid.transport.Binary; +import org.apache.qpid.transport.Connection; +import org.apache.qpid.transport.ConnectionException; +import org.apache.qpid.transport.ConnectionListener; +import org.apache.qpid.transport.Session; +import org.apache.qpid.transport.SessionDelegate; +import org.apache.qpid.transport.TransportException; + +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.ScheduledThreadPoolExecutor; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicReference; +import java.util.concurrent.atomic.AtomicReferenceFieldUpdater; + +public class BrokerLink implements LinkConfig, ConnectionListener +{ + + private static final int CORE_POOL_SIZE = 4; + + private static final ScheduledThreadPoolExecutor _threadPool = + new ScheduledThreadPoolExecutor(CORE_POOL_SIZE); + + + private final String _transport; + private final String _host; + private final int _port; + private final String _remoteVhost; + private final boolean _durable; + private final String _authMechanism; + private final String _username; + private final String _password; + private final VirtualHost _virtualHost; + private UUID _id; + private AtomicBoolean _closing = new AtomicBoolean(); + private final long _createTime = System.currentTimeMillis(); + private Connection _qpidConnection; + private AtomicReference<Thread> _executor = new AtomicReference<Thread>(); + private AtomicInteger _bridgeId = new AtomicInteger(); + + private final ConcurrentHashMap<Bridge,Bridge> _bridges = new ConcurrentHashMap<Bridge,Bridge>(); + private final ConcurrentHashMap<Bridge,Bridge> _activeBridges = new ConcurrentHashMap<Bridge,Bridge>(); + private final ConcurrentLinkedQueue<Bridge> _pendingBridges = new ConcurrentLinkedQueue<Bridge>(); + private String _remoteFederationTag; + + private ConnectionConfig _connectionConfig; + private ConnectionException _exception; + private String _lastErrorMessage; + private int _retryDelay = 1; + private final Runnable _makeConnectionTask = new Runnable() + { + public void run() + { + doMakeConnection(); + } + };; + ; + + public static enum State + { + OPERATIONAL, + DOWN, + ESTABLISHING, + DELETED + } + + + private volatile State _state = State.DOWN; + + private static final AtomicReferenceFieldUpdater<BrokerLink, State> _stateUpdater = + AtomicReferenceFieldUpdater.newUpdater(BrokerLink.class, State.class, "_state"); + + private class ConnectionConfigAdapter implements ConnectionConfig + { + + private UUID _id = BrokerLink.this.getConfigStore().createId(); + + public VirtualHost getVirtualHost() + { + return BrokerLink.this.getVirtualHost(); + } + + public String getAddress() + { + return _host+":"+_port; + } + + public Boolean isIncoming() + { + return false; + } + + public Boolean isSystemConnection() + { + return true; + } + + public Boolean isFederationLink() + { + return true; + } + + public String getAuthId() + { + return _username; + } + + public String getRemoteProcessName() + { + return null; + } + + public Integer getRemotePID() + { + return null; + } + + public Integer getRemoteParentPID() + { + return null; + } + + public ConfigStore getConfigStore() + { + return getVirtualHost().getConfigStore(); + } + + public UUID getId() + { + return _id; + } + + public ConnectionConfigType getConfigType() + { + return ConnectionConfigType.getInstance(); + } + + public ConfiguredObject getParent() + { + return getVirtualHost(); + } + + public boolean isDurable() + { + return false; + } + } + + private class SessionFactory implements Connection.SessionFactory + { + + public Session newSession(final Connection conn, final Binary name, final long expiry) + { + return new ServerSession(conn, new SessionDelegate(), name, expiry, _connectionConfig); + } + }; + + + public BrokerLink(final VirtualHost virtualHost, + final String transport, + final String host, + final int port, + final String remoteVhost, + final boolean durable, + final String authMechanism, final String username, final String password) + { + _virtualHost = virtualHost; + _transport = transport; + _host = host; + _port = port; + _remoteVhost = remoteVhost; + _durable = durable; + _authMechanism = authMechanism; + _username = username; + _password = password; + _id = virtualHost.getConfigStore().createId(); + _qpidConnection = new Connection(); + _connectionConfig = new ConnectionConfigAdapter(); + _qpidConnection.addConnectionListener(this); + + + makeConnection(); + } + + private final boolean updateState(State expected, State newState) + { + return _stateUpdater.compareAndSet(this,expected,newState); + } + + private void makeConnection() + { + _threadPool.execute(_makeConnectionTask); + } + + + + private void doMakeConnection() + { + if(updateState(State.DOWN, State.ESTABLISHING)) + { + try + { + _qpidConnection.connect(_host, _port, _remoteVhost, _username, _password, "ssl".equals(_transport), _authMechanism); + + final Map<String,Object> serverProps = _qpidConnection.getServerProperties(); + _remoteFederationTag = (String) serverProps.get("qpid.federation_tag"); + if(_remoteFederationTag == null) + { + _remoteFederationTag = UUID.fromString(_transport+":"+_host+":"+_port).toString(); + } + _qpidConnection.setSessionFactory(new SessionFactory()); + _qpidConnection.setAuthorizationID(_username == null ? "" : _username); + + updateState(State.ESTABLISHING, State.OPERATIONAL); + + _retryDelay = 1; + + for(Bridge bridge : _bridges.values()) + { + if(_state != State.OPERATIONAL) + { + break; + } + addBridge(bridge); + } + + + } + catch (TransportException e) + { + _lastErrorMessage = e.getMessage(); + if(_retryDelay < 60) + { + _retryDelay <<= 1; + } + + updateState(State.ESTABLISHING, State.DOWN); + _activeBridges.clear(); + scheduleConnectionRetry(); + } + } + } + + private void scheduleConnectionRetry() + { + if(_state != State.DELETED) + { + _threadPool.schedule(_makeConnectionTask, _retryDelay, TimeUnit.SECONDS); + } + } + + public VirtualHost getVirtualHost() + { + return _virtualHost; + } + + public String getTransport() + { + return _transport; + } + + public String getHost() + { + return _host; + } + + public int getPort() + { + return _port; + } + + public String getRemoteVhost() + { + return _remoteVhost; + } + + public UUID getId() + { + return _id; + } + + public LinkConfigType getConfigType() + { + return LinkConfigType.getInstance(); + } + + public ConfiguredObject getParent() + { + return getVirtualHost(); + } + + public boolean isDurable() + { + return _durable; + } + + public String getAuthMechanism() + { + return _authMechanism; + } + + public String getUsername() + { + return _username; + } + + public String getPassword() + { + return _password; + } + + @Override + public boolean equals(final Object o) + { + if (this == o) + { + return true; + } + if (o == null || getClass() != o.getClass()) + { + return false; + } + + final BrokerLink that = (BrokerLink) o; + + if (_port != that._port) + { + return false; + } + if (_host != null ? !_host.equals(that._host) : that._host != null) + { + return false; + } + if (_remoteVhost != null ? !_remoteVhost.equals(that._remoteVhost) : that._remoteVhost != null) + { + return false; + } + if (_transport != null ? !_transport.equals(that._transport) : that._transport != null) + { + return false; + } + + return true; + } + + @Override + public int hashCode() + { + int result = _transport != null ? _transport.hashCode() : 0; + result = 31 * result + (_host != null ? _host.hashCode() : 0); + result = 31 * result + _port; + result = 31 * result + (_remoteVhost != null ? _remoteVhost.hashCode() : 0); + return result; + } + + public void close() + { + if(_closing.compareAndSet(false,true)) + { + // TODO - close connection + for(Bridge bridge : _bridges.values()) + { + bridge.close(); + } + _bridges.clear(); + + _virtualHost.removeBrokerConnection(this); + } + } + + public long getCreateTime() + { + return _createTime; + } + + public void createBridge(final boolean durable, + final boolean dynamic, + final boolean srcIsQueue, + final boolean srcIsLocal, + final String src, + final String dest, + final String key, + final String tag, + final String excludes) + { + if(!_closing.get()) + { + Bridge bridge = new Bridge(this, _bridgeId.incrementAndGet(), durable,dynamic,srcIsQueue,srcIsLocal,src,dest,key,tag,excludes); + if(_bridges.putIfAbsent(bridge, bridge) == null) + { + + addBridge(bridge); + } + } + + + } + + private void addBridge(final Bridge bridge) + { + getConfigStore().addConfiguredObject(bridge); + + if(_state == State.OPERATIONAL && (_activeBridges.putIfAbsent(bridge,bridge) == null)) + { + + + Session session = _qpidConnection.createSession("Bridge(" + + (bridge.isDurable() ? "durable" : "transient") + + "," + (bridge.isDynamic() ? "dynamic" : "static") + + "," + (bridge.isQueueBridge() ? "queue" : "exchange") + + "," + (bridge.isLocalSource() ? "local-src" : "remote-src") + + ",[Source: '" + bridge.getSource() + "']" + + ",[Destination: '" + bridge.getDestination() + "']" + + ",[Key: '" + bridge.getKey() + "']" + + ",[Tag: '" + bridge.getTag() + "']" + + ".[Excludes: '" + bridge.getExcludes() + "'])"); + bridge.setSession(session); + + + if(_closing.get()) + { + bridge.close(); + } + } + + } + + public void opened(final Connection connection) + { + // this method not called + } + + public void exception(final Connection connection, final ConnectionException exception) + { + _exception = exception; + _lastErrorMessage = exception.getMessage(); + + } + + public void closed(final Connection connection) + { + State currentState = _state; + if(currentState != State.DOWN && currentState != State.DELETED && updateState(currentState, State.DOWN)) + { + scheduleConnectionRetry(); + } + } + + public ConfigStore getConfigStore() + { + return getVirtualHost().getConfigStore(); + } + + public String getFederationTag() + { + return getVirtualHost().getFederationTag(); + } + + public String getRemoteFederationTag() + { + return _remoteFederationTag; + } +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/filter/JMSSelectorFilter.java b/java/broker/src/main/java/org/apache/qpid/server/filter/JMSSelectorFilter.java index dacd047fea..f32de03841 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/filter/JMSSelectorFilter.java +++ b/java/broker/src/main/java/org/apache/qpid/server/filter/JMSSelectorFilter.java @@ -22,6 +22,7 @@ package org.apache.qpid.server.filter; import org.apache.log4j.Logger; import org.apache.qpid.AMQException; +import org.apache.qpid.AMQInvalidArgumentException; import org.apache.qpid.server.filter.jms.selector.SelectorParser; import org.apache.qpid.server.queue.Filterable; @@ -33,7 +34,7 @@ public class JMSSelectorFilter implements MessageFilter private String _selector; private BooleanExpression _matcher; - public JMSSelectorFilter(String selector) throws AMQException + public JMSSelectorFilter(String selector) throws AMQInvalidArgumentException { _selector = selector; _matcher = new SelectorParser().parse(selector); diff --git a/java/broker/src/main/java/org/apache/qpid/server/handler/BasicConsumeMethodHandler.java b/java/broker/src/main/java/org/apache/qpid/server/handler/BasicConsumeMethodHandler.java index 0343457a73..d806f9426a 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/handler/BasicConsumeMethodHandler.java +++ b/java/broker/src/main/java/org/apache/qpid/server/handler/BasicConsumeMethodHandler.java @@ -27,7 +27,6 @@ import org.apache.qpid.protocol.AMQConstant; import org.apache.qpid.server.AMQChannel; import org.apache.qpid.server.protocol.AMQProtocolSession; import org.apache.qpid.server.queue.AMQQueue; -import org.apache.qpid.server.security.access.Permission; import org.apache.qpid.server.state.AMQStateManager; import org.apache.qpid.server.state.StateAwareMethodListener; import org.apache.qpid.server.virtualhost.VirtualHost; @@ -102,11 +101,11 @@ public class BasicConsumeMethodHandler implements StateAwareMethodListener<Basic body.getNoLocal(), body.getNowait(), queue)) { throw body.getConnectionException(AMQConstant.ACCESS_REFUSED, "Permission denied"); - } + } else if (queue.isExclusive() && !queue.isDurable() && queue.getExclusiveOwner() != session) { throw body.getConnectionException(AMQConstant.NOT_ALLOWED, - "Queue " + queue.getName() + " is exclusive, but not created on this Connection."); + "Queue " + queue.getNameShortString() + " is exclusive, but not created on this Connection."); } if (body.getConsumerTag() != null) @@ -163,14 +162,14 @@ public class BasicConsumeMethodHandler implements StateAwareMethodListener<Basic { throw body.getChannelException(AMQConstant.ACCESS_REFUSED, "Cannot subscribe to queue " - + queue.getName() + + queue.getNameShortString() + " as it already has an existing exclusive consumer"); } catch (AMQQueue.ExistingSubscriptionPreventsExclusive e) { throw body.getChannelException(AMQConstant.ACCESS_REFUSED, "Cannot subscribe to queue " - + queue.getName() + + queue.getNameShortString() + " exclusively as it already has a consumer"); } diff --git a/java/broker/src/main/java/org/apache/qpid/server/handler/ExchangeDeclareHandler.java b/java/broker/src/main/java/org/apache/qpid/server/handler/ExchangeDeclareHandler.java index 1dd6f1413b..7cfd1fc121 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/handler/ExchangeDeclareHandler.java +++ b/java/broker/src/main/java/org/apache/qpid/server/handler/ExchangeDeclareHandler.java @@ -30,7 +30,6 @@ import org.apache.qpid.server.exchange.Exchange; import org.apache.qpid.server.exchange.ExchangeFactory; import org.apache.qpid.server.exchange.ExchangeRegistry; import org.apache.qpid.server.protocol.AMQProtocolSession; -import org.apache.qpid.server.security.access.Permission; import org.apache.qpid.server.state.AMQStateManager; import org.apache.qpid.server.state.StateAwareMethodListener; import org.apache.qpid.server.virtualhost.VirtualHost; @@ -109,10 +108,10 @@ public class ExchangeDeclareHandler implements StateAwareMethodListener<Exchange } } } - else if (!exchange.getType().equals(body.getType())) + else if (!exchange.getTypeShortString().equals(body.getType())) { - throw new AMQConnectionException(AMQConstant.NOT_ALLOWED, "Attempt to redeclare exchange: " + body.getExchange() + " of type " + exchange.getType() + " to " + body.getType() +".",body.getClazz(), body.getMethod(),body.getMajor(),body.getMinor(),null); + throw new AMQConnectionException(AMQConstant.NOT_ALLOWED, "Attempt to redeclare exchange: " + body.getExchange() + " of type " + exchange.getTypeShortString() + " to " + body.getType() +".",body.getClazz(), body.getMethod(),body.getMajor(),body.getMinor(),null); } } diff --git a/java/broker/src/main/java/org/apache/qpid/server/handler/QueueBindHandler.java b/java/broker/src/main/java/org/apache/qpid/server/handler/QueueBindHandler.java index 57ce7a7240..0de3ded5a1 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/handler/QueueBindHandler.java +++ b/java/broker/src/main/java/org/apache/qpid/server/handler/QueueBindHandler.java @@ -7,9 +7,9 @@ * 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 @@ -21,21 +21,27 @@ package org.apache.qpid.server.handler; import org.apache.log4j.Logger; + import org.apache.qpid.AMQException; -import org.apache.qpid.AMQInvalidRoutingKeyException; -import org.apache.qpid.framing.*; +import org.apache.qpid.framing.AMQMethodBody; +import org.apache.qpid.framing.AMQShortString; +import org.apache.qpid.framing.FieldTable; +import org.apache.qpid.framing.MethodRegistry; +import org.apache.qpid.framing.QueueBindBody; import org.apache.qpid.protocol.AMQConstant; import org.apache.qpid.server.AMQChannel; +import org.apache.qpid.server.binding.Binding; import org.apache.qpid.server.exchange.Exchange; import org.apache.qpid.server.exchange.ExchangeRegistry; import org.apache.qpid.server.protocol.AMQProtocolSession; import org.apache.qpid.server.queue.AMQQueue; import org.apache.qpid.server.queue.QueueRegistry; -import org.apache.qpid.server.security.access.Permission; import org.apache.qpid.server.state.AMQStateManager; import org.apache.qpid.server.state.StateAwareMethodListener; import org.apache.qpid.server.virtualhost.VirtualHost; +import java.util.Map; + public class QueueBindHandler implements StateAwareMethodListener<QueueBindBody> { private static final Logger _log = Logger.getLogger(QueueBindHandler.class); @@ -80,7 +86,7 @@ public class QueueBindHandler implements StateAwareMethodListener<QueueBindBody> if (body.getRoutingKey() == null) { - routingKey = queue.getName(); + routingKey = queue.getNameShortString(); } else { @@ -116,18 +122,26 @@ public class QueueBindHandler implements StateAwareMethodListener<QueueBindBody> else if (queue.isExclusive() && !queue.isDurable() && queue.getExclusiveOwner() != session) { throw body.getConnectionException(AMQConstant.NOT_ALLOWED, - "Queue " + queue.getName() + " is exclusive, but not created on this Connection."); + "Queue " + queue.getNameShortString() + " is exclusive, but not created on this Connection."); } if (!exch.isBound(routingKey, body.getArguments(), queue)) { - queue.bind(exch, routingKey, body.getArguments()); + String bindingKey = String.valueOf(routingKey); + Map<String,Object> arguments = FieldTable.convertToMap(body.getArguments()); + + if(!virtualHost.getBindingFactory().addBinding(bindingKey, queue, exch, arguments)) + { + Binding oldBinding = virtualHost.getBindingFactory().getBinding(bindingKey, queue, exch, arguments); + + Map<String, Object> oldArgs = oldBinding.getArguments(); + if((oldArgs == null && !arguments.isEmpty()) || (oldArgs != null && !oldArgs.equals(arguments))) + { + virtualHost.getBindingFactory().replaceBinding(bindingKey, queue, exch, arguments); + } + } } } - catch (AMQInvalidRoutingKeyException rke) - { - throw body.getChannelException(AMQConstant.INVALID_ROUTING_KEY, routingKey.toString()); - } catch (AMQException e) { throw body.getChannelException(AMQConstant.CHANNEL_ERROR, e.toString()); diff --git a/java/broker/src/main/java/org/apache/qpid/server/handler/QueueDeclareHandler.java b/java/broker/src/main/java/org/apache/qpid/server/handler/QueueDeclareHandler.java index bb57fdbc36..5d5bd761c7 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/handler/QueueDeclareHandler.java +++ b/java/broker/src/main/java/org/apache/qpid/server/handler/QueueDeclareHandler.java @@ -21,6 +21,7 @@ package org.apache.qpid.server.handler; import java.util.UUID; +import java.util.Collections; import java.util.concurrent.atomic.AtomicInteger; import org.apache.log4j.Logger; @@ -150,21 +151,21 @@ public class QueueDeclareHandler implements StateAwareMethodListener<QueueDeclar { Exchange defaultExchange = exchangeRegistry.getDefaultExchange(); - queue.bind(defaultExchange, queueName, null); - _logger.info("Queue " + queueName + " bound to default exchange(" + defaultExchange.getName() + ")"); + virtualHost.getBindingFactory().addBinding(String.valueOf(queueName), queue, defaultExchange, Collections.EMPTY_MAP); + _logger.info("Queue " + queueName + " bound to default exchange(" + defaultExchange.getNameShortString() + ")"); } } } else if (queue.isExclusive() && !queue.isDurable() && queue.getExclusiveOwner() != session) { throw body.getConnectionException(AMQConstant.NOT_ALLOWED, - "Queue " + queue.getName() + " is exclusive, but not created on this Connection."); + "Queue " + queue.getNameShortString() + " is exclusive, but not created on this Connection."); } else if(!body.getPassive() && ((queue.isExclusive()) != body.getExclusive())) { throw body.getChannelException(AMQConstant.ALREADY_EXISTS, - "Cannot re-declare queue '" + queue.getName() + "' with different exclusivity (was: " + "Cannot re-declare queue '" + queue.getNameShortString() + "' with different exclusivity (was: " + queue.isExclusive() + " requested " + body.getExclusive() + ")"); } else if (!body.getPassive() && body.getExclusive() && !queue.getExclusiveOwner().equals(queue.isDurable() ? session.getPrincipal().getName() : session)) @@ -178,13 +179,13 @@ public class QueueDeclareHandler implements StateAwareMethodListener<QueueDeclar else if(!body.getPassive() && queue.isAutoDelete() != body.getAutoDelete()) { throw body.getChannelException(AMQConstant.ALREADY_EXISTS, - "Cannot re-declare queue '" + queue.getName() + "' with different auto-delete (was: " + "Cannot re-declare queue '" + queue.getNameShortString() + "' with different auto-delete (was: " + queue.isAutoDelete() + " requested " + body.getAutoDelete() + ")"); } else if(!body.getPassive() && queue.isDurable() != body.getDurable()) { throw body.getChannelException(AMQConstant.ALREADY_EXISTS, - "Cannot re-declare queue '" + queue.getName() + "' with different durability (was: " + "Cannot re-declare queue '" + queue.getNameShortString() + "' with different durability (was: " + queue.isDurable() + " requested " + body.getDurable() + ")"); } diff --git a/java/broker/src/main/java/org/apache/qpid/server/handler/QueueDeleteHandler.java b/java/broker/src/main/java/org/apache/qpid/server/handler/QueueDeleteHandler.java index 3d58ec2133..93acc94816 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/handler/QueueDeleteHandler.java +++ b/java/broker/src/main/java/org/apache/qpid/server/handler/QueueDeleteHandler.java @@ -7,9 +7,9 @@ * 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 @@ -30,11 +30,9 @@ import org.apache.qpid.server.queue.QueueRegistry; import org.apache.qpid.server.queue.AMQQueue; import org.apache.qpid.server.state.AMQStateManager; import org.apache.qpid.server.state.StateAwareMethodListener; -import org.apache.qpid.server.store.MessageStore; import org.apache.qpid.server.store.DurableConfigurationStore; import org.apache.qpid.server.virtualhost.VirtualHost; import org.apache.qpid.server.AMQChannel; -import org.apache.qpid.server.security.access.Permission; public class QueueDeleteHandler implements StateAwareMethodListener<QueueDeleteBody> { @@ -75,7 +73,7 @@ public class QueueDeleteHandler implements StateAwareMethodListener<QueueDeleteB throw body.getChannelNotFoundException(channelId); } - //get the default queue on the channel: + //get the default queue on the channel: queue = channel.getDefaultQueue(); } else @@ -104,7 +102,7 @@ public class QueueDeleteHandler implements StateAwareMethodListener<QueueDeleteB } else { - + //Perform ACLs if (!virtualHost.getAccessManager().authoriseDelete(session, queue)) { @@ -113,7 +111,7 @@ public class QueueDeleteHandler implements StateAwareMethodListener<QueueDeleteB else if (queue.isExclusive() && !queue.isDurable() && queue.getExclusiveOwner() != session) { throw body.getConnectionException(AMQConstant.NOT_ALLOWED, - "Queue " + queue.getName() + " is exclusive, but not created on this Connection."); + "Queue " + queue.getNameShortString() + " is exclusive, but not created on this Connection."); } int purged = queue.delete(); diff --git a/java/broker/src/main/java/org/apache/qpid/server/handler/QueueUnbindHandler.java b/java/broker/src/main/java/org/apache/qpid/server/handler/QueueUnbindHandler.java index 31401ce9d9..29c30de9cc 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/handler/QueueUnbindHandler.java +++ b/java/broker/src/main/java/org/apache/qpid/server/handler/QueueUnbindHandler.java @@ -106,23 +106,16 @@ public class QueueUnbindHandler implements StateAwareMethodListener<QueueUnbindB throw body.getConnectionException(AMQConstant.ACCESS_REFUSED, "Permission denied"); } - try + if(virtualHost.getBindingFactory().getBinding(String.valueOf(routingKey), queue, exch, FieldTable.convertToMap(body.getArguments())) == null) { - queue.unBind(exch, routingKey, body.getArguments()); + throw body.getChannelException(AMQConstant.NOT_FOUND,"No such binding"); } - catch (AMQInvalidRoutingKeyException rke) - { - throw body.getChannelException(AMQConstant.INVALID_ROUTING_KEY, routingKey.toString()); - } - catch (AMQException e) + else { - if(e.getErrorCode() == AMQConstant.NOT_FOUND) - { - throw body.getChannelException(AMQConstant.NOT_FOUND,e.getMessage(),e); - } - throw body.getChannelException(AMQConstant.CHANNEL_ERROR, e.toString()); + virtualHost.getBindingFactory().removeBinding(String.valueOf(routingKey), queue, exch, FieldTable.convertToMap(body.getArguments())); } + if (_log.isInfoEnabled()) { _log.info("Binding queue " + queue + " to exchange " + exch + " with routing key " + routingKey); diff --git a/java/broker/src/main/java/org/apache/qpid/server/logging/subjects/BindingLogSubject.java b/java/broker/src/main/java/org/apache/qpid/server/logging/subjects/BindingLogSubject.java index fd171fea5a..69139d38a3 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/logging/subjects/BindingLogSubject.java +++ b/java/broker/src/main/java/org/apache/qpid/server/logging/subjects/BindingLogSubject.java @@ -20,7 +20,6 @@ */ package org.apache.qpid.server.logging.subjects; -import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.server.exchange.Exchange; import org.apache.qpid.server.queue.AMQQueue; @@ -49,13 +48,13 @@ public class BindingLogSubject extends AbstractLogSubject * @param exchange * @param queue */ - public BindingLogSubject(AMQShortString routingKey, Exchange exchange, + public BindingLogSubject(String routingKey, Exchange exchange, AMQQueue queue) { setLogStringWithFormat(BINDING_FORMAT, queue.getVirtualHost().getName(), - exchange.getType(), - exchange.getName(), - queue.getName(), + exchange.getTypeShortString(), + exchange.getNameShortString(), + queue.getNameShortString(), routingKey); } diff --git a/java/broker/src/main/java/org/apache/qpid/server/logging/subjects/ExchangeLogSubject.java b/java/broker/src/main/java/org/apache/qpid/server/logging/subjects/ExchangeLogSubject.java index 21e5f5e4ce..0fc2d7392f 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/logging/subjects/ExchangeLogSubject.java +++ b/java/broker/src/main/java/org/apache/qpid/server/logging/subjects/ExchangeLogSubject.java @@ -41,6 +41,6 @@ public class ExchangeLogSubject extends AbstractLogSubject public ExchangeLogSubject(Exchange exchange, VirtualHost vhost) { setLogStringWithFormat(BINDING_FORMAT, vhost.getName(), - exchange.getType(), exchange.getName()); + exchange.getTypeShortString(), exchange.getNameShortString()); } } diff --git a/java/broker/src/main/java/org/apache/qpid/server/logging/subjects/QueueLogSubject.java b/java/broker/src/main/java/org/apache/qpid/server/logging/subjects/QueueLogSubject.java index b132d9e93f..fd97318e8b 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/logging/subjects/QueueLogSubject.java +++ b/java/broker/src/main/java/org/apache/qpid/server/logging/subjects/QueueLogSubject.java @@ -40,6 +40,6 @@ public class QueueLogSubject extends AbstractLogSubject { setLogStringWithFormat(LOG_FORMAT, queue.getVirtualHost().getName(), - queue.getName()); + queue.getNameShortString()); } } diff --git a/java/broker/src/main/java/org/apache/qpid/server/message/AMQMessageHeader.java b/java/broker/src/main/java/org/apache/qpid/server/message/AMQMessageHeader.java index 6c9311c3de..faac14f8a7 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/message/AMQMessageHeader.java +++ b/java/broker/src/main/java/org/apache/qpid/server/message/AMQMessageHeader.java @@ -42,6 +42,10 @@ public interface AMQMessageHeader String getReplyTo(); + String getReplyToExchange(); + String getReplyToRoutingKey(); + + Object getHeader(String name); boolean containsHeaders(Set<String> names); diff --git a/java/broker/src/main/java/org/apache/qpid/server/message/ContentHeaderBodyAdapter.java b/java/broker/src/main/java/org/apache/qpid/server/message/ContentHeaderBodyAdapter.java index 4a1f8dd191..194835ac02 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/message/ContentHeaderBodyAdapter.java +++ b/java/broker/src/main/java/org/apache/qpid/server/message/ContentHeaderBodyAdapter.java @@ -85,6 +85,19 @@ public class ContentHeaderBodyAdapter implements AMQMessageHeader return getProperties().getReplyToAsString(); } + public String getReplyToExchange() + { + // TODO + return getReplyTo(); + } + + public String getReplyToRoutingKey() + { + // TODO + return getReplyTo(); + + } + public Object getHeader(String name) { FieldTable ft = getProperties().getHeaders(); diff --git a/java/broker/src/main/java/org/apache/qpid/server/message/MessageMetaData.java b/java/broker/src/main/java/org/apache/qpid/server/message/MessageMetaData.java index b34a8fc470..2f8c2e09a2 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/message/MessageMetaData.java +++ b/java/broker/src/main/java/org/apache/qpid/server/message/MessageMetaData.java @@ -278,6 +278,18 @@ public class MessageMetaData implements StorableMessageMetaData return getProperties().getReplyToAsString(); } + public String getReplyToExchange() + { + // TODO + return getReplyTo(); + } + + public String getReplyToRoutingKey() + { + // TODO + return getReplyTo(); + } + public Object getHeader(String name) { FieldTable ft = getProperties().getHeaders(); diff --git a/java/broker/src/main/java/org/apache/qpid/server/message/MessageTransferHeader.java b/java/broker/src/main/java/org/apache/qpid/server/message/MessageTransferHeader.java index 7fac7ab164..a15e16a64f 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/message/MessageTransferHeader.java +++ b/java/broker/src/main/java/org/apache/qpid/server/message/MessageTransferHeader.java @@ -105,6 +105,30 @@ class MessageTransferHeader implements AMQMessageHeader } } + public String getReplyToExchange() + { + if (_messageProps != null && _messageProps.getReplyTo() != null) + { + return _messageProps.getReplyTo().getExchange(); + } + else + { + return null; + } + } + + public String getReplyToRoutingKey() + { + if (_messageProps != null && _messageProps.getReplyTo() != null) + { + return _messageProps.getReplyTo().getRoutingKey(); + } + else + { + return null; + } + } + public Object getHeader(String name) { Map<String, Object> appHeaders = _messageProps == null ? null : _messageProps.getApplicationHeaders(); diff --git a/java/broker/src/main/java/org/apache/qpid/server/message/MessageTransferMessage.java b/java/broker/src/main/java/org/apache/qpid/server/message/MessageTransferMessage.java index e866ad5078..baa5dce14f 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/message/MessageTransferMessage.java +++ b/java/broker/src/main/java/org/apache/qpid/server/message/MessageTransferMessage.java @@ -119,7 +119,7 @@ public class MessageTransferMessage implements InboundMessage, ServerMessage public ByteBuffer getBody() { ByteBuffer body = getMetaData().getBody(); - if(body == null) + if(body == null && getSize() != 0l) { final int size = (int) getSize(); int pos = 0; diff --git a/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolEngine.java b/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolEngine.java index ea8fbbd68f..ec74f79ace 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolEngine.java +++ b/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolEngine.java @@ -20,50 +20,16 @@ */ package org.apache.qpid.server.protocol; -import java.io.IOException; -import java.net.InetSocketAddress; -import java.net.SocketAddress; -import java.nio.ByteBuffer; -import java.security.Principal; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.CopyOnWriteArrayList; -import java.util.concurrent.CopyOnWriteArraySet; -import java.util.concurrent.atomic.AtomicLong; -import java.util.concurrent.atomic.AtomicMarkableReference; -import java.util.concurrent.atomic.AtomicBoolean; - -import javax.management.JMException; -import javax.security.sasl.SaslServer; - import org.apache.log4j.Logger; import org.apache.mina.transport.vmpipe.VmPipeAddress; + import org.apache.qpid.AMQChannelException; import org.apache.qpid.AMQConnectionException; import org.apache.qpid.AMQException; import org.apache.qpid.codec.AMQCodecFactory; import org.apache.qpid.codec.AMQDecoder; import org.apache.qpid.common.ClientProperties; -import org.apache.qpid.framing.AMQBody; -import org.apache.qpid.framing.AMQDataBlock; -import org.apache.qpid.framing.AMQFrame; -import org.apache.qpid.framing.AMQMethodBody; -import org.apache.qpid.framing.AMQProtocolHeaderException; -import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.framing.ChannelCloseOkBody; -import org.apache.qpid.framing.ConnectionCloseBody; -import org.apache.qpid.framing.ContentBody; -import org.apache.qpid.framing.ContentHeaderBody; -import org.apache.qpid.framing.FieldTable; -import org.apache.qpid.framing.HeartbeatBody; -import org.apache.qpid.framing.MethodDispatcher; -import org.apache.qpid.framing.MethodRegistry; -import org.apache.qpid.framing.ProtocolInitiation; -import org.apache.qpid.framing.ProtocolVersion; +import org.apache.qpid.framing.*; import org.apache.qpid.pool.Job; import org.apache.qpid.pool.ReferenceCountingExecutorService; import org.apache.qpid.protocol.AMQConstant; @@ -71,6 +37,10 @@ import org.apache.qpid.protocol.AMQMethodEvent; import org.apache.qpid.protocol.AMQMethodListener; import org.apache.qpid.protocol.ProtocolEngine; import org.apache.qpid.server.AMQChannel; +import org.apache.qpid.server.configuration.ConfigStore; +import org.apache.qpid.server.configuration.ConfiguredObject; +import org.apache.qpid.server.configuration.ConnectionConfig; +import org.apache.qpid.server.configuration.ConnectionConfigType; import org.apache.qpid.server.handler.ServerMethodDispatcherImpl; import org.apache.qpid.server.logging.LogActor; import org.apache.qpid.server.logging.LogSubject; @@ -85,12 +55,31 @@ import org.apache.qpid.server.output.ProtocolOutputConverterRegistry; import org.apache.qpid.server.registry.ApplicationRegistry; import org.apache.qpid.server.state.AMQState; import org.apache.qpid.server.state.AMQStateManager; -import org.apache.qpid.server.virtualhost.VirtualHostRegistry; import org.apache.qpid.server.virtualhost.VirtualHost; +import org.apache.qpid.server.virtualhost.VirtualHostRegistry; import org.apache.qpid.transport.NetworkDriver; import org.apache.qpid.transport.Sender; -public class AMQProtocolEngine implements ProtocolEngine, Managable, AMQProtocolSession +import javax.management.JMException; +import javax.security.sasl.SaslServer; +import java.io.IOException; +import java.net.InetSocketAddress; +import java.net.SocketAddress; +import java.nio.ByteBuffer; +import java.security.Principal; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.CopyOnWriteArraySet; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicLong; + +public class AMQProtocolEngine implements ProtocolEngine, Managable, AMQProtocolSession, ConnectionConfig { private static final Logger _logger = Logger.getLogger(AMQProtocolEngine.class); @@ -161,6 +150,8 @@ public class AMQProtocolEngine implements ProtocolEngine, Managable, AMQProtocol private ReferenceCountingExecutorService _poolReference = ReferenceCountingExecutorService.getInstance(); private long _maxFrameSize; private final AtomicBoolean _closing = new AtomicBoolean(false); + private final UUID _id; + private final ConfigStore _configStore; public ManagedObject getManagedObject() { @@ -181,6 +172,10 @@ public class AMQProtocolEngine implements ProtocolEngine, Managable, AMQProtocol _logSubject = new ConnectionLogSubject(this); + _configStore = virtualHostRegistry.getConfigStore(); + _id = _configStore.createId(); + + _actor.message(ConnectionMessages.CON_OPEN(null, null, false, false)); } @@ -765,6 +760,8 @@ public class AMQProtocolEngine implements ProtocolEngine, Managable, AMQProtocol public void closeProtocolSession() { + getConfigStore().removeConfiguredObject(this); + _networkDriver.close(); try { @@ -902,6 +899,8 @@ public class AMQProtocolEngine implements ProtocolEngine, Managable, AMQProtocol _virtualHost = virtualHost; _virtualHost.getConnectionRegistry().registerConnection(this); + + _configStore.addConfiguredObject(this); try { @@ -1067,4 +1066,69 @@ public class AMQProtocolEngine implements ProtocolEngine, Managable, AMQProtocol } } + public Boolean isIncoming() + { + return true; + } + + public Boolean isSystemConnection() + { + return false; + } + + public Boolean isFederationLink() + { + return false; + } + + public String getAuthId() + { + return getAuthorizedID().getName(); + } + + public Integer getRemotePID() + { + return null; + } + + public String getRemoteProcessName() + { + return null; + } + + public Integer getRemoteParentPID() + { + return null; + } + + public ConfigStore getConfigStore() + { + return _configStore; + } + + public ConnectionConfigType getConfigType() + { + return ConnectionConfigType.getInstance(); + } + + public ConfiguredObject getParent() + { + return getVirtualHost(); + } + + public boolean isDurable() + { + return false; + } + + public UUID getId() + { + return _id; + } + + public String getAddress() + { + return String.valueOf(getRemoteAddress()); + } + } diff --git a/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolSessionMBean.java b/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolSessionMBean.java index 0562d04b7b..8d832a6a79 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolSessionMBean.java +++ b/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolSessionMBean.java @@ -37,8 +37,19 @@ */ package org.apache.qpid.server.protocol; -import java.util.Date; -import java.util.List; +import org.apache.qpid.AMQException; +import org.apache.qpid.framing.AMQShortString; +import org.apache.qpid.framing.ConnectionCloseBody; +import org.apache.qpid.framing.MethodRegistry; +import org.apache.qpid.management.common.mbeans.ManagedConnection; +import org.apache.qpid.management.common.mbeans.annotations.MBeanConstructor; +import org.apache.qpid.management.common.mbeans.annotations.MBeanDescription; +import org.apache.qpid.protocol.AMQConstant; +import org.apache.qpid.server.AMQChannel; +import org.apache.qpid.server.logging.actors.CurrentActor; +import org.apache.qpid.server.logging.actors.ManagementActor; +import org.apache.qpid.server.management.AMQManagedObject; +import org.apache.qpid.server.management.ManagedObject; import javax.management.JMException; import javax.management.MBeanException; @@ -55,22 +66,8 @@ import javax.management.openmbean.SimpleType; import javax.management.openmbean.TabularData; import javax.management.openmbean.TabularDataSupport; import javax.management.openmbean.TabularType; - -import org.apache.qpid.AMQException; -import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.framing.ConnectionCloseBody; -import org.apache.qpid.framing.MethodRegistry; -import org.apache.qpid.management.common.mbeans.ManagedConnection; -import org.apache.qpid.management.common.mbeans.annotations.MBeanConstructor; -import org.apache.qpid.management.common.mbeans.annotations.MBeanDescription; -import org.apache.qpid.protocol.AMQConstant; -import org.apache.qpid.server.AMQChannel; -import org.apache.qpid.server.logging.actors.CurrentActor; -import org.apache.qpid.server.logging.actors.ManagementActor; -import org.apache.qpid.server.logging.LogActor; -import org.apache.qpid.server.logging.RootMessageLogger; -import org.apache.qpid.server.management.AMQManagedObject; -import org.apache.qpid.server.management.ManagedObject; +import java.util.Date; +import java.util.List; /** * This MBean class implements the management interface. In order to make more attributes, operations and notifications @@ -255,7 +252,7 @@ public class AMQProtocolSessionMBean extends AMQManagedObject implements Managed Object[] itemValues = { channel.getChannelId(), channel.isTransactional(), - (channel.getDefaultQueue() != null) ? channel.getDefaultQueue().getName().asString() : null, + (channel.getDefaultQueue() != null) ? channel.getDefaultQueue().getNameShortString().asString() : null, channel.getUnacknowledgedMessageMap().size(), channel.getBlocking() }; @@ -291,7 +288,7 @@ public class AMQProtocolSessionMBean extends AMQManagedObject implements Managed // then the CurrentActor could be set in our JMX Proxy object. // As it is we need to set the CurrentActor on all MBean methods // Ideally we would not have a single method that can be called from - // two contexts. + // two contexts. boolean removeActor = false; if (CurrentActor.get() == null) { diff --git a/java/broker/src/main/java/org/apache/qpid/server/protocol/MultiVersionProtocolEngine.java b/java/broker/src/main/java/org/apache/qpid/server/protocol/MultiVersionProtocolEngine.java index 9a1c6c9418..b3cb90fc6e 100755 --- a/java/broker/src/main/java/org/apache/qpid/server/protocol/MultiVersionProtocolEngine.java +++ b/java/broker/src/main/java/org/apache/qpid/server/protocol/MultiVersionProtocolEngine.java @@ -20,14 +20,14 @@ */ package org.apache.qpid.server.protocol; +import org.apache.log4j.Logger; + import org.apache.qpid.protocol.ProtocolEngine; -import org.apache.qpid.server.registry.IApplicationRegistry; -import org.apache.qpid.transport.NetworkDriver; -import org.apache.qpid.transport.Connection; -import org.apache.qpid.transport.ConnectionDelegate; import org.apache.qpid.server.protocol.MultiVersionProtocolEngineFactory.VERSION; +import org.apache.qpid.server.registry.IApplicationRegistry; import org.apache.qpid.server.transport.ServerConnection; -import org.apache.log4j.Logger; +import org.apache.qpid.transport.ConnectionDelegate; +import org.apache.qpid.transport.NetworkDriver; import java.net.SocketAddress; import java.nio.ByteBuffer; @@ -239,10 +239,10 @@ private static final byte[] AMQP_0_9_1_HEADER = final ConnectionDelegate connDelegate = new org.apache.qpid.server.transport.ServerConnectionDelegate(_appRegistry, _fqdn); - Connection conn = new ServerConnection(); + ServerConnection conn = new ServerConnection(); conn.setConnectionDelegate(connDelegate); - return new ProtocolEngine_0_10( conn, _networkDriver); + return new ProtocolEngine_0_10( conn, _networkDriver, _appRegistry); } }; diff --git a/java/broker/src/main/java/org/apache/qpid/server/protocol/ProtocolEngineFactory_0_10.java b/java/broker/src/main/java/org/apache/qpid/server/protocol/ProtocolEngineFactory_0_10.java deleted file mode 100755 index 7c3adf8b7d..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/server/protocol/ProtocolEngineFactory_0_10.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * - * 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.protocol; - -import org.apache.qpid.protocol.ProtocolEngineFactory; -import org.apache.qpid.protocol.ProtocolEngine; -import org.apache.qpid.transport.NetworkDriver; -import org.apache.qpid.transport.Connection; -import org.apache.qpid.transport.ConnectionDelegate; -import org.apache.qpid.server.transport.ServerConnection; -import org.apache.qpid.server.protocol.ProtocolEngine_0_10; - -public class ProtocolEngineFactory_0_10 implements ProtocolEngineFactory -{ - private ConnectionDelegate _delegate; - - public ProtocolEngineFactory_0_10(ConnectionDelegate delegate) - { - _delegate = delegate; - } - - public ProtocolEngine newProtocolEngine(NetworkDriver networkDriver) - { - Connection conn = new ServerConnection(); - conn.setConnectionDelegate(_delegate); - return new ProtocolEngine_0_10(conn, networkDriver); - } -} diff --git a/java/broker/src/main/java/org/apache/qpid/server/protocol/ProtocolEngine_0_10.java b/java/broker/src/main/java/org/apache/qpid/server/protocol/ProtocolEngine_0_10.java index e3cd3acd98..473f68028d 100755 --- a/java/broker/src/main/java/org/apache/qpid/server/protocol/ProtocolEngine_0_10.java +++ b/java/broker/src/main/java/org/apache/qpid/server/protocol/ProtocolEngine_0_10.java @@ -26,23 +26,34 @@ import org.apache.qpid.transport.Connection; import org.apache.qpid.transport.network.InputHandler; import org.apache.qpid.transport.network.Assembler; import org.apache.qpid.transport.network.Disassembler; +import org.apache.qpid.server.configuration.*; +import org.apache.qpid.server.transport.ServerConnection; +import org.apache.qpid.server.registry.IApplicationRegistry; import java.net.SocketAddress; +import java.util.UUID; -public class ProtocolEngine_0_10 extends InputHandler implements ProtocolEngine +public class ProtocolEngine_0_10 extends InputHandler implements ProtocolEngine, ConnectionConfig { public static final int MAX_FRAME_SIZE = 64 * 1024 - 1; private NetworkDriver _networkDriver; private long _readBytes; private long _writtenBytes; - private Connection _connection; + private ServerConnection _connection; + private final UUID _id; + private final IApplicationRegistry _appRegistry; - public ProtocolEngine_0_10(Connection conn, NetworkDriver networkDriver) + public ProtocolEngine_0_10(ServerConnection conn, + NetworkDriver networkDriver, + final IApplicationRegistry appRegistry) { super(new Assembler(conn)); _connection = conn; + _connection.setConnectionConfig(this); _networkDriver = networkDriver; + _id = appRegistry.getConfigStore().createId(); + _appRegistry = appRegistry; } public void setNetworkDriver(NetworkDriver driver) @@ -50,6 +61,14 @@ public class ProtocolEngine_0_10 extends InputHandler implements ProtocolEngine _networkDriver = driver; Disassembler dis = new Disassembler(driver, MAX_FRAME_SIZE); _connection.setSender(dis); + _connection.onOpen(new Runnable() + { + public void run() + { + getConfigStore().addConfiguredObject(ProtocolEngine_0_10.this); + } + }); + } public SocketAddress getRemoteAddress() @@ -81,4 +100,81 @@ public class ProtocolEngine_0_10 extends InputHandler implements ProtocolEngine { //Todo } + + public VirtualHostConfig getVirtualHost() + { + return _connection.getVirtualHost(); + } + + public String getAddress() + { + return getRemoteAddress().toString(); + } + + public Boolean isIncoming() + { + return true; + } + + public Boolean isSystemConnection() + { + return false; + } + + public Boolean isFederationLink() + { + return false; + } + + public String getAuthId() + { + return _connection.getAuthorizationID(); + } + + public String getRemoteProcessName() + { + return null; + } + + public Integer getRemotePID() + { + return null; + } + + public Integer getRemoteParentPID() + { + return null; + } + + public ConfigStore getConfigStore() + { + return _appRegistry.getConfigStore(); + } + + public UUID getId() + { + return _id; + } + + public ConnectionConfigType getConfigType() + { + return ConnectionConfigType.getInstance(); + } + + public ConfiguredObject getParent() + { + return getVirtualHost(); + } + + public boolean isDurable() + { + return false; + } + + @Override + public void closed() + { + super.closed(); + getConfigStore().removeConfiguredObject(this); + } } diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/AMQPriorityQueue.java b/java/broker/src/main/java/org/apache/qpid/server/queue/AMQPriorityQueue.java index 51fbff76f4..d8986ec303 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/queue/AMQPriorityQueue.java +++ b/java/broker/src/main/java/org/apache/qpid/server/queue/AMQPriorityQueue.java @@ -21,9 +21,11 @@ package org.apache.qpid.server.queue; import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.server.virtualhost.VirtualHost; -import org.apache.qpid.server.subscription.SubscriptionList; import org.apache.qpid.server.subscription.Subscription; +import org.apache.qpid.server.subscription.SubscriptionList; +import org.apache.qpid.server.virtualhost.VirtualHost; + +import java.util.Map; public class AMQPriorityQueue extends SimpleAMQQueue { @@ -32,18 +34,18 @@ public class AMQPriorityQueue extends SimpleAMQQueue final AMQShortString owner, final boolean autoDelete, final VirtualHost virtualHost, - int priorities) + int priorities, Map<String, Object> arguments) { - super(name, durable, owner, autoDelete, virtualHost, new PriorityQueueList.Factory(priorities)); + super(name, durable, owner, autoDelete, virtualHost, new PriorityQueueList.Factory(priorities),arguments); } public AMQPriorityQueue(String queueName, boolean durable, String owner, boolean autoDelete, - VirtualHost virtualHost, int priorities) + VirtualHost virtualHost, int priorities, Map<String,Object> arguments) { - this(new AMQShortString(queueName), durable, new AMQShortString(owner),autoDelete,virtualHost,priorities); + this(queueName == null ? null : new AMQShortString(queueName), durable, owner == null ? null : new AMQShortString(owner),autoDelete,virtualHost,priorities, arguments); } public int getPriorities() diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueue.java b/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueue.java index 028f7e15a4..81ea2083e0 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueue.java +++ b/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueue.java @@ -20,44 +20,48 @@ */ package org.apache.qpid.server.queue; -import org.apache.qpid.server.management.Managable; -import org.apache.qpid.server.management.ManagedObject; +import org.apache.qpid.AMQException; +import org.apache.qpid.framing.AMQShortString; +import org.apache.qpid.server.AMQChannel; +import org.apache.qpid.server.binding.Binding; +import org.apache.qpid.server.configuration.QueueConfig; import org.apache.qpid.server.configuration.QueueConfiguration; import org.apache.qpid.server.exchange.Exchange; import org.apache.qpid.server.exchange.ExchangeReferrer; -import org.apache.qpid.server.virtualhost.VirtualHost; -import org.apache.qpid.server.message.ServerMessage; -import org.apache.qpid.server.subscription.Subscription; -import org.apache.qpid.server.AMQChannel; -import org.apache.qpid.server.store.TransactionLogResource; +import org.apache.qpid.server.management.Managable; +import org.apache.qpid.server.management.ManagedObject; import org.apache.qpid.server.security.PrincipalHolder; +import org.apache.qpid.server.store.TransactionLogResource; +import org.apache.qpid.server.subscription.Subscription; import org.apache.qpid.server.txn.ServerTransaction; -import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.framing.FieldTable; -import org.apache.qpid.AMQException; +import org.apache.qpid.server.virtualhost.VirtualHost; import java.util.List; -import java.util.Set; import java.util.Map; +import java.util.Set; -public interface AMQQueue extends Managable, Comparable<AMQQueue>, ExchangeReferrer, TransactionLogResource +public interface AMQQueue extends Managable, Comparable<AMQQueue>, ExchangeReferrer, TransactionLogResource, BaseQueue, + QueueConfig { boolean getDeleteOnNoConsumers(); void setDeleteOnNoConsumers(boolean b); + void addBinding(Binding binding); + + void removeBinding(Binding binding); + + List<Binding> getBindings(); + + int getBindingCount(); public interface Context { QueueEntry getLastSeenEntry(); } - AMQShortString getName(); - void setNoLocal(boolean b); - boolean isDurable(); - boolean isAutoDelete(); AMQShortString getOwner(); @@ -69,14 +73,6 @@ public interface AMQQueue extends Managable, Comparable<AMQQueue>, ExchangeRefer VirtualHost getVirtualHost(); - - void bind(Exchange exchange, AMQShortString routingKey, FieldTable arguments) throws AMQException; - - void unBind(Exchange exchange, AMQShortString routingKey, FieldTable arguments) throws AMQException; - - List<ExchangeBinding> getExchangeBindings(); - - void registerSubscription(final Subscription subscription, final boolean exclusive) throws AMQException; void unregisterSubscription(final Subscription subscription) throws AMQException; @@ -86,6 +82,8 @@ public interface AMQQueue extends Managable, Comparable<AMQQueue>, ExchangeRefer int getActiveConsumerCount(); + boolean hasExclusiveSubscriber(); + boolean isUnused(); boolean isEmpty(); @@ -107,8 +105,6 @@ public interface AMQQueue extends Managable, Comparable<AMQQueue>, ExchangeRefer int delete() throws AMQException; - QueueEntry enqueue(ServerMessage message) throws AMQException; - void requeue(QueueEntry entry); void requeue(QueueEntryImpl storeContext, Subscription subscription); @@ -122,6 +118,8 @@ public interface AMQQueue extends Managable, Comparable<AMQQueue>, ExchangeRefer void addQueueDeleteTask(final Task task); + void removeQueueDeleteTask(final Task task); + List<QueueEntry> getMessagesOnTheQueue(); diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueFactory.java b/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueFactory.java index d4a5b3258b..fd7dd4cc60 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueFactory.java +++ b/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueFactory.java @@ -23,16 +23,21 @@ package org.apache.qpid.server.queue; import org.apache.qpid.AMQException; import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.framing.FieldTable; -import org.apache.qpid.server.configuration.QueueConfiguration; import org.apache.qpid.server.virtualhost.VirtualHost; +import org.apache.qpid.server.configuration.QueueConfiguration; import java.util.Map; +import java.util.HashMap; public class AMQQueueFactory { public static final AMQShortString X_QPID_PRIORITIES = new AMQShortString("x-qpid-priorities"); + private static final String QPID_LVQ_KEY = "qpid.LVQ_key"; + private static final String QPID_LAST_VALUE_QUEUE = "qpid.last_value_queue"; + private static final String QPID_LAST_VALUE_QUEUE_KEY = "qpid.last_value_queue_key"; + private abstract static class QueueProperty { @@ -130,21 +135,60 @@ public class AMQQueueFactory boolean autoDelete, VirtualHost virtualHost, final FieldTable arguments) { - final int priorities = arguments == null ? 1 : arguments.containsKey(X_QPID_PRIORITIES) ? arguments.getInteger(X_QPID_PRIORITIES) : 1; + return createAMQQueueImpl(name == null ? null : name.toString(), + durable, + owner == null ? null : owner.toString(), + autoDelete, + virtualHost, + FieldTable.convertToMap(arguments)); + } - AMQQueue q = null; - if(priorities > 1) + + public static AMQQueue createAMQQueueImpl(String queueName, + boolean durable, + String owner, + boolean autoDelete, + VirtualHost virtualHost, Map<String, Object> arguments) + { + int priorities = 1; + String conflationKey = null; + if(arguments != null) { - q = new AMQPriorityQueue(name, durable, owner, autoDelete, virtualHost, priorities); + if(arguments.containsKey(QPID_LAST_VALUE_QUEUE) || arguments.containsKey(QPID_LAST_VALUE_QUEUE_KEY)) + { + conflationKey = (String) arguments.get(QPID_LAST_VALUE_QUEUE_KEY); + if(conflationKey == null) + { + conflationKey = QPID_LVQ_KEY; + } + } + else if(arguments.containsKey(X_QPID_PRIORITIES)) + { + Object prioritiesObj = arguments.get(X_QPID_PRIORITIES); + if(prioritiesObj instanceof Number) + { + priorities = ((Number)prioritiesObj).intValue(); + } + } + } + + AMQQueue q; + if(conflationKey != null) + { + q = new ConflationQueue(queueName, durable, owner, autoDelete, virtualHost, arguments, conflationKey); + } + else if(priorities > 1) + { + q = new AMQPriorityQueue(queueName, durable, owner, autoDelete, virtualHost, priorities, arguments); } else { - q = new SimpleAMQQueue(name, durable, owner, autoDelete, virtualHost); + q = new SimpleAMQQueue(queueName, durable, owner, autoDelete, virtualHost, arguments); } //Register the new queue virtualHost.getQueueRegistry().registerQueue(q); - q.configure(virtualHost.getConfiguration().getQueueConfiguration(name.asString())); + q.configure(virtualHost.getConfiguration().getQueueConfiguration(queueName)); if(arguments != null) { @@ -158,29 +202,43 @@ public class AMQQueueFactory } return q; + } + public static AMQQueue createAMQQueueImpl(QueueConfiguration config, VirtualHost host) throws AMQException { - AMQShortString queueName = new AMQShortString(config.getName()); + String queueName = config.getName(); boolean durable = config.getDurable(); boolean autodelete = config.getAutoDelete(); - AMQShortString owner = (config.getOwner() != null) ? new AMQShortString(config.getOwner()) : null; - FieldTable arguments = null; - boolean priority = config.getPriority(); - int priorities = config.getPriorities(); - if(priority || priorities > 0) + String owner = config.getOwner(); + Map<String,Object> arguments = null; + if(config.isLVQ() || config.getLVQKey() != null) { if(arguments == null) { - arguments = new FieldTable(); + arguments = new HashMap<String,Object>(); } - if (priorities < 0) + arguments.put(QPID_LAST_VALUE_QUEUE, 1); + arguments.put(QPID_LAST_VALUE_QUEUE_KEY, config.getLVQKey() == null ? QPID_LVQ_KEY : config.getLVQKey()); + } + else + { + boolean priority = config.getPriority(); + int priorities = config.getPriorities(); + if(priority || priorities > 0) { - priorities = 10; + if(arguments == null) + { + arguments = new HashMap<String,Object>(); + } + if (priorities < 0) + { + priorities = 10; + } + arguments.put("x-qpid-priorities", priorities); } - arguments.put(new AMQShortString("x-qpid-priorities"), priorities); } AMQQueue q = createAMQQueueImpl(queueName, durable, owner, autodelete, host, arguments); @@ -188,38 +246,4 @@ public class AMQQueueFactory return q; } - public static AMQQueue createAMQQueueImpl(String queueName, - boolean durable, - String owner, - boolean autoDelete, - VirtualHost virtualHost, Map<String, Object> arguments) - throws AMQException - { - int priorities = 1; - if(arguments != null && arguments.containsKey(X_QPID_PRIORITIES)) - { - Object prioritiesObj = arguments.get(X_QPID_PRIORITIES); - if(prioritiesObj instanceof Number) - { - priorities = ((Number)prioritiesObj).intValue(); - } - } - - - AMQQueue q = null; - if(priorities > 1) - { - q = new AMQPriorityQueue(queueName, durable, owner, autoDelete, virtualHost, priorities); - } - else - { - q = new SimpleAMQQueue(queueName, durable, owner, autoDelete, virtualHost); - } - - //Register the new queue - virtualHost.getQueueRegistry().registerQueue(q); - q.configure(virtualHost.getConfiguration().getQueueConfiguration(queueName)); - return q; - - } } diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueMBean.java b/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueMBean.java index c21d73cc41..6102e525e3 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueMBean.java +++ b/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueMBean.java @@ -95,7 +95,7 @@ public class AMQQueueMBean extends AMQManagedObject implements ManagedQueue, Que { super(ManagedQueue.class, ManagedQueue.TYPE); _queue = queue; - _queueName = jmxEncode(new StringBuffer(queue.getName()), 0).toString(); + _queueName = jmxEncode(new StringBuffer(queue.getNameShortString()), 0).toString(); } public ManagedObject getParentObject() @@ -252,7 +252,7 @@ public class AMQQueueMBean extends AMQManagedObject implements ManagedQueue, Que { throw new IllegalArgumentException("Capacity must not be less than FlowResumeCapacity"); } - + _queue.setCapacity(capacity); } @@ -267,10 +267,10 @@ public class AMQQueueMBean extends AMQManagedObject implements ManagedQueue, Que { throw new IllegalArgumentException("FlowResumeCapacity must not exceed Capacity"); } - + _queue.setFlowResumeCapacity(flowResumeCapacity); } - + public boolean isFlowOverfull() { return _queue.isOverfull(); @@ -309,7 +309,7 @@ public class AMQQueueMBean extends AMQManagedObject implements ManagedQueue, Que public void notifyClients(NotificationCheck notification, AMQQueue queue, String notificationMsg) { // important : add log to the log file - monitoring tools may be looking for this - _logger.info(notification.name() + " On Queue " + queue.getName() + " - " + notificationMsg); + _logger.info(notification.name() + " On Queue " + queue.getNameShortString() + " - " + notificationMsg); notificationMsg = notification.name() + " " + notificationMsg; _lastNotification = @@ -509,7 +509,7 @@ public class AMQQueueMBean extends AMQManagedObject implements ManagedQueue, Que private String[] getMessageTransferMessageHeaderProps(MessageTransferMessage msg) { List<String> list = new ArrayList<String>(); - + AMQMessageHeader header = msg.getMessageHeader(); MessageProperties msgProps = msg.getHeader().get(MessageProperties.class); diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/BaseQueue.java b/java/broker/src/main/java/org/apache/qpid/server/queue/BaseQueue.java new file mode 100644 index 0000000000..05e0efd9a6 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/queue/BaseQueue.java @@ -0,0 +1,42 @@ +/* + * + * 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.queue; + +import org.apache.qpid.server.message.ServerMessage; +import org.apache.qpid.server.store.TransactionLogResource; +import org.apache.qpid.AMQException; +import org.apache.qpid.framing.AMQShortString; + +public interface BaseQueue extends TransactionLogResource +{ + public static interface PostEnqueueAction + { + public void onEnqueue(QueueEntry entry); + } + + void enqueue(ServerMessage message) throws AMQException; + void enqueue(ServerMessage message, PostEnqueueAction action) throws AMQException; + + boolean isDurable(); + + AMQShortString getNameShortString(); +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/ConflationQueue.java b/java/broker/src/main/java/org/apache/qpid/server/queue/ConflationQueue.java new file mode 100644 index 0000000000..26c0d7cf26 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/queue/ConflationQueue.java @@ -0,0 +1,42 @@ +/* + * + * 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.queue; + +import org.apache.qpid.server.virtualhost.VirtualHost; + +import java.util.Map; + +public class ConflationQueue extends SimpleAMQQueue +{ + protected ConflationQueue(String name, + boolean durable, + String owner, + boolean autoDelete, + VirtualHost virtualHost, + Map<String, Object> args, + String conflationKey) + { + super(name, durable, owner, autoDelete, virtualHost, new ConflationQueueList.Factory(conflationKey), args); + } + + +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/ConflationQueueList.java b/java/broker/src/main/java/org/apache/qpid/server/queue/ConflationQueueList.java new file mode 100644 index 0000000000..9a6e5c884a --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/queue/ConflationQueueList.java @@ -0,0 +1,168 @@ +/* + * + * 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.queue; + +import org.apache.qpid.framing.AMQShortString; +import org.apache.qpid.framing.BasicContentHeaderProperties; +import org.apache.qpid.AMQException; +import org.apache.qpid.server.store.StoreContext; +import org.apache.qpid.server.subscription.Subscription; +import org.apache.qpid.server.AMQChannel; +import org.apache.qpid.server.txn.ServerTransaction; +import org.apache.qpid.server.txn.AutoCommitTransaction; +import org.apache.qpid.server.message.ServerMessage; + +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicReference; + +public class ConflationQueueList extends SimpleQueueEntryList +{ + + private final String _conflationKey; + private final ConcurrentHashMap<Object, AtomicReference<QueueEntry>> _latestValuesMap = + new ConcurrentHashMap<Object, AtomicReference<QueueEntry>>(); + + public ConflationQueueList(AMQQueue queue, String conflationKey) + { + super(queue); + _conflationKey = conflationKey; + } + + @Override + protected ConflationQueueEntry createQueueEntry(ServerMessage message) + { + return new ConflationQueueEntry(this, message); + } + + + @Override + public QueueEntry add(final ServerMessage message) + { + ConflationQueueEntry entry = (ConflationQueueEntry) (super.add(message)); + AtomicReference<QueueEntry> latestValueReference = null; + + Object value = message.getMessageHeader().getHeader(_conflationKey); + if(value != null) + { + latestValueReference = _latestValuesMap.get(value); + if(latestValueReference == null) + { + _latestValuesMap.putIfAbsent(value, new AtomicReference<QueueEntry>(entry)); + latestValueReference = _latestValuesMap.get(value); + } + QueueEntry oldEntry; + + do + { + oldEntry = latestValueReference.get(); + } + while(oldEntry.compareTo(entry) < 0 && !latestValueReference.compareAndSet(oldEntry, entry)); + + if(oldEntry.compareTo(entry) < 0) + { + // We replaced some other entry to become the newest value + if(oldEntry.acquire()) + { + discardEntry(oldEntry); + } + } + else if (oldEntry.compareTo(entry) > 0) + { + // A newer entry came along + discardEntry(entry); + + } + } + + entry.setLatestValueReference(latestValueReference); + return entry; + } + + private void discardEntry(final QueueEntry entry) + { + if(entry.acquire()) + { + ServerTransaction txn = new AutoCommitTransaction(getQueue().getVirtualHost().getTransactionLog()); + txn.dequeue(entry.getQueue(),entry.getMessage(), + new ServerTransaction.Action() + { + public void postCommit() + { + entry.discard(); + } + + public void onRollback() + { + + } + }); + } + } + + private final class ConflationQueueEntry extends QueueEntryImpl + { + + + private AtomicReference<QueueEntry> _latestValueReference; + + public ConflationQueueEntry(SimpleQueueEntryList queueEntryList, ServerMessage message) + { + super(queueEntryList, message); + } + + + public void release() + { + super.release(); + + if(_latestValueReference != null) + { + if(_latestValueReference.get() != this) + { + discardEntry(this); + } + } + + } + + public void setLatestValueReference(final AtomicReference<QueueEntry> latestValueReference) + { + _latestValueReference = latestValueReference; + } + } + + static class Factory implements QueueEntryListFactory + { + private final String _conflationKey; + + Factory(String conflationKey) + { + _conflationKey = conflationKey; + } + + public QueueEntryList createQueueEntryList(AMQQueue queue) + { + return new ConflationQueueList(queue, _conflationKey); + } + } + +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/DefaultQueueRegistry.java b/java/broker/src/main/java/org/apache/qpid/server/queue/DefaultQueueRegistry.java index aea485e749..d76487073d 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/queue/DefaultQueueRegistry.java +++ b/java/broker/src/main/java/org/apache/qpid/server/queue/DefaultQueueRegistry.java @@ -20,7 +20,6 @@ */ package org.apache.qpid.server.queue; -import org.apache.qpid.AMQException; import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.server.virtualhost.VirtualHost; @@ -46,7 +45,7 @@ public class DefaultQueueRegistry implements QueueRegistry public void registerQueue(AMQQueue queue) { - _queueMap.put(queue.getName(), queue); + _queueMap.put(queue.getNameShortString(), queue); } public void unregisterQueue(AMQShortString name) diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/ExchangeBinding.java b/java/broker/src/main/java/org/apache/qpid/server/queue/ExchangeBinding.java deleted file mode 100644 index 2fd8e32fcd..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/server/queue/ExchangeBinding.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * - * 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.queue; - -import org.apache.qpid.server.exchange.Exchange; -import org.apache.qpid.server.logging.actors.CurrentActor; -import org.apache.qpid.server.logging.messages.BindingMessages; -import org.apache.qpid.server.logging.subjects.BindingLogSubject; -import org.apache.qpid.server.logging.LogSubject; -import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.framing.FieldTable; -import org.apache.qpid.AMQException; - -public class ExchangeBinding -{ - private final Exchange _exchange; - private final AMQShortString _routingKey; - private final FieldTable _arguments; - - private static final FieldTable EMPTY_ARGUMENTS = new FieldTable(); - private LogSubject _logSubject; - - ExchangeBinding(AMQShortString routingKey, Exchange exchange, AMQQueue queue, FieldTable arguments) - { - _routingKey = routingKey == null ? AMQShortString.EMPTY_STRING : routingKey; - _exchange = exchange; - _arguments = arguments == null ? EMPTY_ARGUMENTS : arguments; - _logSubject = new BindingLogSubject(routingKey,exchange,queue); - - CurrentActor.get().message(_logSubject, BindingMessages.BND_CREATED(String.valueOf(_arguments), arguments != null)); - } - - - - void unbind(AMQQueue queue) throws AMQException - { - _exchange.deregisterQueue(_routingKey, queue, _arguments); - - CurrentActor.get().message(_logSubject, BindingMessages.BND_DELETED()); - } - - public Exchange getExchange() - { - return _exchange; - } - - public AMQShortString getRoutingKey() - { - return _routingKey; - } - - public FieldTable getArguments() - { - return _arguments; - } - - public int hashCode() - { - return (_exchange == null ? 0 : _exchange.hashCode()) - + (_routingKey == null ? 0 : _routingKey.hashCode()); - } - - public boolean equals(Object o) - { - if (!(o instanceof ExchangeBinding)) - { - return false; - } - ExchangeBinding eb = (ExchangeBinding) o; - return _exchange.equals(eb._exchange) - && _routingKey.equals(eb._routingKey); - } -}
\ No newline at end of file diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/ExchangeBindings.java b/java/broker/src/main/java/org/apache/qpid/server/queue/ExchangeBindings.java deleted file mode 100644 index 89262aee59..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/server/queue/ExchangeBindings.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * - * 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.queue; - -import java.util.HashSet; -import java.util.List; -import java.util.concurrent.CopyOnWriteArrayList; - -import org.apache.qpid.AMQException; -import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.framing.FieldTable; -import org.apache.qpid.server.exchange.Exchange; - -/** - * When a queue is deleted, it should be deregistered from any - * exchange it has been bound to. This class assists in this task, - * by keeping track of all bindings for a given queue. - */ -class ExchangeBindings -{ - private final List<ExchangeBinding> _bindings = new CopyOnWriteArrayList<ExchangeBinding>(); - private final AMQQueue _queue; - - ExchangeBindings(AMQQueue queue) - { - _queue = queue; - } - - /** - * Adds the specified binding to those being tracked. - * @param routingKey the routing key with which the queue whose bindings - * are being tracked by the instance has been bound to the exchange - * @param exchange the exchange bound to - */ - void addBinding(AMQShortString routingKey, FieldTable arguments, Exchange exchange) - { - _bindings.add(new ExchangeBinding(routingKey, exchange, _queue, arguments)); - } - - - public boolean remove(AMQShortString routingKey, FieldTable arguments, Exchange exchange) - { - return _bindings.remove(new ExchangeBinding(routingKey, exchange, _queue, arguments)); - } - - - /** - * Deregisters this queue from any exchange it has been bound to - */ - void deregister() throws AMQException - { - //remove duplicates at this point - HashSet<ExchangeBinding> copy = new HashSet<ExchangeBinding>(_bindings); - for (ExchangeBinding b : copy) - { - b.unbind(_queue); - } - } - - List<ExchangeBinding> getExchangeBindings() - { - return _bindings; - } -} diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/IncomingMessage.java b/java/broker/src/main/java/org/apache/qpid/server/queue/IncomingMessage.java index da4173d5d3..2d2fb3a214 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/queue/IncomingMessage.java +++ b/java/broker/src/main/java/org/apache/qpid/server/queue/IncomingMessage.java @@ -63,7 +63,7 @@ public class IncomingMessage implements Filterable, InboundMessage, EnqueableMes * delivered. It is <b>cleared after delivery has been attempted</b>. Any persistent record of destinations is done * by the message handle. */ - private ArrayList<AMQQueue> _destinationQueues; + private ArrayList<? extends BaseQueue> _destinationQueues; private long _expiration; @@ -131,7 +131,7 @@ public class IncomingMessage implements Filterable, InboundMessage, EnqueableMes } - public ArrayList<AMQQueue> getDestinationQueues() + public ArrayList<? extends BaseQueue> getDestinationQueues() { return _destinationQueues; } @@ -225,7 +225,7 @@ public class IncomingMessage implements Filterable, InboundMessage, EnqueableMes } - public void enqueue(final ArrayList<AMQQueue> queues) + public void enqueue(final ArrayList<? extends BaseQueue> queues) { _destinationQueues = queues; } diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntry.java b/java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntry.java index a50e2b561d..edd1e0bdc3 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntry.java +++ b/java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntry.java @@ -28,6 +28,7 @@ public interface QueueEntry extends Comparable<QueueEntry>, Filterable { + public static enum State { AVAILABLE, @@ -163,6 +164,8 @@ public interface QueueEntry extends Comparable<QueueEntry>, Filterable boolean expired() throws AMQException; + boolean isAvailable(); + boolean isAcquired(); boolean acquire(); diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntryImpl.java b/java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntryImpl.java index 5873e8f566..ada7726fc0 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntryImpl.java +++ b/java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntryImpl.java @@ -20,20 +20,23 @@ */ package org.apache.qpid.server.queue; +import org.apache.log4j.Logger; + import org.apache.qpid.AMQException; -import org.apache.qpid.server.subscription.Subscription; -import org.apache.qpid.server.message.ServerMessage; -import org.apache.qpid.server.message.MessageReference; -import org.apache.qpid.server.message.AMQMessageHeader; import org.apache.qpid.server.exchange.Exchange; +import org.apache.qpid.server.message.AMQMessageHeader; +import org.apache.qpid.server.message.MessageReference; +import org.apache.qpid.server.message.ServerMessage; +import org.apache.qpid.server.subscription.Subscription; import org.apache.qpid.server.txn.AutoCommitTransaction; import org.apache.qpid.server.txn.ServerTransaction; -import org.apache.log4j.Logger; -import java.util.*; -import java.util.concurrent.atomic.AtomicReferenceFieldUpdater; -import java.util.concurrent.atomic.AtomicLongFieldUpdater; +import java.util.HashSet; +import java.util.List; +import java.util.Set; import java.util.concurrent.CopyOnWriteArraySet; +import java.util.concurrent.atomic.AtomicLongFieldUpdater; +import java.util.concurrent.atomic.AtomicReferenceFieldUpdater; public class QueueEntryImpl implements QueueEntry @@ -154,6 +157,11 @@ public class QueueEntryImpl implements QueueEntry } + public boolean isAvailable() + { + return _state == AVAILABLE_STATE; + } + public boolean isAcquired() { return _state.getState() == State.ACQUIRED; @@ -408,7 +416,7 @@ public class QueueEntryImpl implements QueueEntry if(alternateExchange != null) { - final List<AMQQueue> rerouteQueues = alternateExchange.route(new InboundMessageAdapter(this)); + final List<? extends BaseQueue> rerouteQueues = alternateExchange.route(new InboundMessageAdapter(this)); final ServerMessage message = getMessage(); if(rerouteQueues != null && rerouteQueues.size() != 0) { @@ -419,9 +427,9 @@ public class QueueEntryImpl implements QueueEntry { try { - for(AMQQueue queue : rerouteQueues) + for(BaseQueue queue : rerouteQueues) { - QueueEntry entry = queue.enqueue(message); + queue.enqueue(message); } } catch (AMQException e) diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/SimpleAMQQueue.java b/java/broker/src/main/java/org/apache/qpid/server/queue/SimpleAMQQueue.java index 825aa9795e..d25d73b383 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/queue/SimpleAMQQueue.java +++ b/java/broker/src/main/java/org/apache/qpid/server/queue/SimpleAMQQueue.java @@ -1,39 +1,51 @@ package org.apache.qpid.server.queue; -import java.util.*; -import java.util.concurrent.CopyOnWriteArrayList; -import java.util.concurrent.Executor; -import java.util.concurrent.atomic.*; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; - -import javax.management.JMException; - import org.apache.log4j.Logger; + import org.apache.qpid.AMQException; import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.framing.FieldTable; import org.apache.qpid.pool.ReadWriteRunnable; import org.apache.qpid.pool.ReferenceCountingExecutorService; +import org.apache.qpid.server.AMQChannel; +import org.apache.qpid.server.binding.Binding; +import org.apache.qpid.server.configuration.ConfigStore; +import org.apache.qpid.server.configuration.ConfiguredObject; +import org.apache.qpid.server.configuration.QueueConfigType; import org.apache.qpid.server.configuration.QueueConfiguration; import org.apache.qpid.server.exchange.Exchange; +import org.apache.qpid.server.logging.LogActor; +import org.apache.qpid.server.logging.LogSubject; +import org.apache.qpid.server.logging.actors.CurrentActor; +import org.apache.qpid.server.logging.actors.QueueActor; +import org.apache.qpid.server.logging.messages.QueueMessages; +import org.apache.qpid.server.logging.subjects.QueueLogSubject; import org.apache.qpid.server.management.ManagedObject; +import org.apache.qpid.server.message.ServerMessage; import org.apache.qpid.server.registry.ApplicationRegistry; +import org.apache.qpid.server.security.PrincipalHolder; import org.apache.qpid.server.subscription.Subscription; import org.apache.qpid.server.subscription.SubscriptionList; -import org.apache.qpid.server.virtualhost.VirtualHost; -import org.apache.qpid.server.message.ServerMessage; -import org.apache.qpid.server.security.PrincipalHolder; -import org.apache.qpid.server.logging.actors.CurrentActor; -import org.apache.qpid.server.logging.actors.QueueActor; -import org.apache.qpid.server.logging.subjects.QueueLogSubject; -import org.apache.qpid.server.logging.LogSubject; -import org.apache.qpid.server.logging.LogActor; -import org.apache.qpid.server.logging.messages.QueueMessages; -import org.apache.qpid.server.AMQChannel; -import org.apache.qpid.server.txn.ServerTransaction; import org.apache.qpid.server.txn.AutoCommitTransaction; import org.apache.qpid.server.txn.LocalTransaction; +import org.apache.qpid.server.txn.ServerTransaction; +import org.apache.qpid.server.virtualhost.VirtualHost; + +import javax.management.JMException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.EnumSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.Executor; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.atomic.AtomicReference; /* * @@ -81,7 +93,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener private Exchange _alternateExchange; /** Used to track bindings to exchanges so that on deletion they can easily be cancelled. */ - private final ExchangeBindings _bindings = new ExchangeBindings(this); + protected final QueueEntryList _entries; @@ -102,8 +114,15 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener private final AtomicLong _totalMessagesReceived = new AtomicLong(); + private final AtomicLong _dequeueCount = new AtomicLong(); + private final AtomicLong _dequeueSize = new AtomicLong(); + private final AtomicLong _enqueueSize = new AtomicLong(); + private final AtomicLong _persistentMessageEnqueueSize = new AtomicLong(); + private final AtomicLong _persistentMessageDequeueSize = new AtomicLong(); + private final AtomicLong _persistentMessageEnqueueCount = new AtomicLong();; + private final AtomicLong _persistentMessageDequeueCount = new AtomicLong(); - + private final AtomicInteger _bindingCountHigh = new AtomicInteger(); /** max allowed size(KB) of a single message */ public long _maximumMessageSize = ApplicationRegistry.getInstance().getConfiguration().getMaximumMessageSize(); @@ -151,18 +170,38 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener private final AtomicBoolean _overfull = new AtomicBoolean(false); private boolean _deleteOnNoConsumers; + private final CopyOnWriteArrayList<Binding> _bindings = new CopyOnWriteArrayList<Binding>(); + private UUID _id; + private final Map<String, Object> _arguments; + + //TODO + private long _createTime = System.currentTimeMillis(); + - protected SimpleAMQQueue(AMQShortString name, boolean durable, AMQShortString owner, boolean autoDelete, VirtualHost virtualHost) + protected SimpleAMQQueue(AMQShortString name, boolean durable, AMQShortString owner, boolean autoDelete, VirtualHost virtualHost, Map<String,Object> arguments) { - this(name, durable, owner, autoDelete, virtualHost, new SimpleQueueEntryList.Factory()); + this(name, durable, owner, autoDelete, virtualHost, new SimpleQueueEntryList.Factory(),arguments); } + public SimpleAMQQueue(String queueName, boolean durable, String owner, boolean autoDelete, VirtualHost virtualHost, Map<String, Object> arguments) + { + this(queueName, durable, owner,autoDelete,virtualHost,new SimpleQueueEntryList.Factory(),arguments); + } + + public SimpleAMQQueue(String queueName, boolean durable, String owner, boolean autoDelete, VirtualHost virtualHost, QueueEntryListFactory entryListFactory, Map<String, Object> arguments) + { + this(queueName == null ? null : new AMQShortString(queueName), durable, owner == null ? null : new AMQShortString(owner),autoDelete,virtualHost,entryListFactory, arguments); + } + + + protected SimpleAMQQueue(AMQShortString name, boolean durable, AMQShortString owner, boolean autoDelete, VirtualHost virtualHost, - QueueEntryListFactory entryListFactory) + QueueEntryListFactory entryListFactory, + Map<String,Object> arguments) { if (name == null) @@ -182,6 +221,9 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener _autoDelete = autoDelete; _virtualHost = virtualHost; _entries = entryListFactory.createQueueEntryList(this); + _arguments = arguments; + + _id = virtualHost.getConfigStore().createId(); _asyncDelivery = ReferenceCountingExecutorService.getInstance().acquireExecutorService(); @@ -208,6 +250,8 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener durable, !durable, priorities > 0)); + getConfigStore().addConfiguredObject(this); + try { _managedObject = new AMQQueueMBean(this); @@ -222,12 +266,6 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener } - public SimpleAMQQueue(String queueName, boolean durable, String owner, boolean autoDelete, VirtualHost virtualHost) - throws AMQException - { - this(new AMQShortString(queueName), durable, owner == null ? null : new AMQShortString(owner),autoDelete,virtualHost); - } - public void resetNotifications() { // This ensure that the notification checks for the configured alerts are created. @@ -244,7 +282,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener _asyncDelivery.execute(runnable); } - public AMQShortString getName() + public AMQShortString getNameShortString() { return _name; } @@ -254,6 +292,21 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener _nolocal = nolocal; } + public UUID getId() + { + return _id; + } + + public QueueConfigType getConfigType() + { + return QueueConfigType.getInstance(); + } + + public ConfiguredObject getParent() + { + return getVirtualHost(); + } + public boolean isDurable() { return _durable; @@ -284,7 +337,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener public Map<String, Object> getArguments() { - return null; + return _arguments; } public boolean isAutoDelete() @@ -313,56 +366,9 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener return _virtualHost; } - // ------ bind and unbind - - public void bind(Exchange exchange, String bindingKey, Map<String, Object> arguments) throws AMQException - { - - FieldTable fieldTable = FieldTable.convertToFieldTable(arguments); - AMQShortString routingKey = new AMQShortString(bindingKey); - - exchange.registerQueue(routingKey, this, fieldTable); - - if (isDurable() && exchange.isDurable()) - { - - _virtualHost.getDurableConfigurationStore().bindQueue(exchange, routingKey, this, fieldTable); - } - - _bindings.addBinding(routingKey, fieldTable, exchange); - } - - - public void bind(Exchange exchange, AMQShortString routingKey, FieldTable arguments) throws AMQException - { - - exchange.registerQueue(routingKey, this, arguments); - if (isDurable() && exchange.isDurable()) - { - _virtualHost.getDurableConfigurationStore().bindQueue(exchange, routingKey, this, arguments); - } - - _bindings.addBinding(routingKey, arguments, exchange); - } - - public void unBind(Exchange exchange, AMQShortString routingKey, FieldTable arguments) throws AMQException + public String getName() { - exchange.deregisterQueue(routingKey, this, arguments); - if (isDurable() && exchange.isDurable()) - { - _virtualHost.getDurableConfigurationStore().unbindQueue(exchange, routingKey, this, arguments); - } - - boolean removed = _bindings.remove(routingKey, arguments, exchange); - if (!removed) - { - _logger.error("Mismatch between queue bindings and exchange record of bindings"); - } - } - - public List<ExchangeBinding> getExchangeBindings() - { - return new ArrayList<ExchangeBinding>(_bindings.getExchangeBindings()); + return getNameShortString().toString(); } // ------ Manage Subscriptions @@ -370,7 +376,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener public synchronized void registerSubscription(final Subscription subscription, final boolean exclusive) throws AMQException { - if (isExclusiveSubscriber()) + if (hasExclusiveSubscriber()) { throw new ExistingExclusiveSubscription(); } @@ -459,17 +465,54 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener _deleteOnNoConsumers = b; } + public void addBinding(final Binding binding) + { + _bindings.add(binding); + int bindingCount = _bindings.size(); + int bindingCountHigh; + while(bindingCount > (bindingCountHigh = _bindingCountHigh.get())) + { + if(_bindingCountHigh.compareAndSet(bindingCountHigh, bindingCount)) + { + break; + } + } + } + + public int getBindingCountHigh() + { + return _bindingCountHigh.get(); + } + + public void removeBinding(final Binding binding) + { + _bindings.remove(binding); + } + + public List<Binding> getBindings() + { + return Collections.unmodifiableList(_bindings); + } + + public int getBindingCount() + { + return getBindings().size(); + } // ------ Enqueue / Dequeue + public void enqueue(ServerMessage message) throws AMQException + { + enqueue(message, null); + } - public QueueEntry enqueue(ServerMessage message) throws AMQException + public void enqueue(ServerMessage message, PostEnqueueAction action) throws AMQException { incrementQueueCount(); incrementQueueSize(message); - _totalMessagesReceived.incrementAndGet(); + QueueEntry entry; Subscription exclusiveSub = _exclusiveSubscriber; @@ -554,7 +597,11 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener _managedObject.checkForNotification(entry.getMessage()); } - return entry; + if(action != null) + { + action.onEnqueue(entry); + } + } private void deliverToSubscription(final Subscription sub, final QueueEntry entry) @@ -596,7 +643,14 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener private void incrementQueueSize(final ServerMessage message) { - getAtomicQueueSize().addAndGet(message.getSize()); + long size = message.getSize(); + getAtomicQueueSize().addAndGet(size); + _enqueueSize.addAndGet(size); + if(message.isPersistent() && isDurable()) + { + _persistentMessageEnqueueSize.addAndGet(size); + _persistentMessageEnqueueCount.incrementAndGet(); + } } private void incrementQueueCount() @@ -654,7 +708,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener SubscriptionList.SubscriptionNodeIterator subscriberIter = _subscriptionList.iterator(); // iterate over all the subscribers, and if they are in advance of this queue entry then move them backwards - while (subscriberIter.advance()) + while (subscriberIter.advance() && entry.isAvailable()) { Subscription sub = subscriberIter.getNode().getSubscription(); @@ -702,12 +756,21 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener private void decrementQueueSize(final QueueEntry entry) { - getAtomicQueueSize().addAndGet(-entry.getMessage().getSize()); + final ServerMessage message = entry.getMessage(); + long size = message.getSize(); + getAtomicQueueSize().addAndGet(-size); + _dequeueSize.addAndGet(size); + if(message.isPersistent() && isDurable()) + { + _persistentMessageDequeueSize.addAndGet(size); + _persistentMessageDequeueCount.incrementAndGet(); + } } void decrementQueueCount() { getAtomicQueueCount().decrementAndGet(); + _dequeueCount.incrementAndGet(); } public boolean resend(final QueueEntry entry, final Subscription subscription) throws AMQException @@ -834,7 +897,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener public int compareTo(final AMQQueue o) { - return _name.compareTo(o.getName()); + return _name.compareTo(o.getNameShortString()); } public AtomicInteger getAtomicQueueCount() @@ -847,7 +910,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener return _atomicQueueSize; } - private boolean isExclusiveSubscriber() + public boolean hasExclusiveSubscriber() { return _exclusiveSubscriber != null; } @@ -1099,6 +1162,45 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener } + public void purge(final long request) + { + if(request == 0l) + { + clearQueue(); + } + else if(request > 0l) + { + + QueueEntryIterator queueListIterator = _entries.iterator(); + long count = 0; + + ServerTransaction txn = new LocalTransaction(getVirtualHost().getTransactionLog()); + + while (queueListIterator.advance()) + { + QueueEntry node = queueListIterator.getNode(); + if (!node.isDeleted() && node.acquire()) + { + dequeueEntry(node, txn); + if(++count == request) + { + break; + } + } + + } + + txn.commit(); + + + } + } + + public long getCreateTime() + { + return _createTime; + } + // ------ Management functions public void deleteMessageFromTop() @@ -1172,11 +1274,21 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener _deleteTaskList.add(task); } + public void removeQueueDeleteTask(final Task task) + { + _deleteTaskList.remove(task); + } + public int delete() throws AMQException { if (!_deleted.getAndSet(true)) { + for(Binding b : getBindings()) + { + _virtualHost.getBindingFactory().removeBinding(b); + } + SubscriptionList.SubscriptionNodeIterator subscriptionIter = _subscriptionList.iterator(); while (subscriptionIter.advance()) @@ -1188,8 +1300,8 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener } } - _bindings.deregister(); _virtualHost.getQueueRegistry().unregisterQueue(_name); + getConfigStore().removeConfiguredObject(this); List<QueueEntry> entries = getMessagesOnTheQueue(new QueueEntryFilter() { @@ -1214,7 +1326,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener for(final QueueEntry entry : entries) { adapter.setEntry(entry); - final List<AMQQueue> rerouteQueues = _alternateExchange.route(adapter); + final List<? extends BaseQueue> rerouteQueues = _alternateExchange.route(adapter); final ServerMessage message = entry.getMessage(); if(rerouteQueues != null & rerouteQueues.size() != 0) { @@ -1226,9 +1338,9 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener { try { - for(AMQQueue queue : rerouteQueues) + for(BaseQueue queue : rerouteQueues) { - QueueEntry entry = queue.enqueue(message); + queue.enqueue(message); } } catch (AMQException e) @@ -1479,7 +1591,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener // next entry they are interested in yet. This would lead to holding on to references to expired messages, etc // which would give us memory "leak". - if (!isExclusiveSubscriber()) + if (!hasExclusiveSubscriber()) { advanceAllSubscriptions(); } @@ -1820,7 +1932,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener public void setFlowResumeCapacity(long flowResumeCapacity) { _flowResumeCapacity = flowResumeCapacity; - + checkCapacity(); } @@ -1919,9 +2031,50 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener } + public ConfigStore getConfigStore() + { + return getVirtualHost().getConfigStore(); + } + + public long getMessageDequeueCount() + { + return _dequeueCount.get(); + } + + public long getTotalEnqueueSize() + { + return _enqueueSize.get(); + } + + public long getTotalDequeueSize() + { + return _dequeueSize.get(); + } + + public long getPersistentByteEnqueues() + { + return _persistentMessageEnqueueSize.get(); + } + + public long getPersistentByteDequeues() + { + return _persistentMessageDequeueSize.get(); + } + + public long getPersistentMsgEnqueues() + { + return _persistentMessageEnqueueCount.get(); + } + + public long getPersistentMsgDequeues() + { + return _persistentMessageDequeueCount.get(); + } + + @Override public String toString() { - return String.valueOf(getName()); + return String.valueOf(getNameShortString()); } } diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/SimpleQueueEntryList.java b/java/broker/src/main/java/org/apache/qpid/server/queue/SimpleQueueEntryList.java index d27a5ed234..8721da0f78 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/queue/SimpleQueueEntryList.java +++ b/java/broker/src/main/java/org/apache/qpid/server/queue/SimpleQueueEntryList.java @@ -61,11 +61,9 @@ public class SimpleQueueEntryList implements QueueEntryList { _deletes.incrementAndGet(); QueueEntryImpl head = _head.nextNode(); - boolean deleted = head.isDeleted(); while(head._next != null && head.isDeleted()) { - deleted = true; final QueueEntryImpl newhead = head.nextNode(); if(newhead != null) { @@ -77,11 +75,6 @@ public class SimpleQueueEntryList implements QueueEntryList head = _head.nextNode(); } - if(!deleted) - { - deleted = true; - } - if(_deletes.get() > 1000L) { _deletes.set(0L); @@ -135,7 +128,7 @@ public class SimpleQueueEntryList implements QueueEntryList public QueueEntry add(ServerMessage message) { - QueueEntryImpl node = new QueueEntryImpl(this, message); + QueueEntryImpl node = createQueueEntry(message); for (;;) { QueueEntryImpl tail = _tail; @@ -160,6 +153,11 @@ public class SimpleQueueEntryList implements QueueEntryList } } + protected QueueEntryImpl createQueueEntry(ServerMessage message) + { + return new QueueEntryImpl(this, message); + } + public QueueEntry next(QueueEntry node) { return ((QueueEntryImpl)node).getNext(); diff --git a/java/broker/src/main/java/org/apache/qpid/server/registry/ApplicationRegistry.java b/java/broker/src/main/java/org/apache/qpid/server/registry/ApplicationRegistry.java index 5cb379f10d..2c4c0a0570 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/registry/ApplicationRegistry.java +++ b/java/broker/src/main/java/org/apache/qpid/server/registry/ApplicationRegistry.java @@ -20,24 +20,33 @@ */ package org.apache.qpid.server.registry; -import java.net.InetSocketAddress; -import java.util.HashMap; -import java.util.Map; - import org.apache.commons.configuration.ConfigurationException; import org.apache.log4j.Logger; + +import org.apache.qpid.qmf.QMFService; +import org.apache.qpid.server.configuration.BrokerConfig; +import org.apache.qpid.server.configuration.ConfigStore; import org.apache.qpid.server.configuration.ServerConfiguration; +import org.apache.qpid.server.configuration.SystemConfig; +import org.apache.qpid.server.configuration.SystemConfigImpl; +import org.apache.qpid.server.configuration.VirtualHostConfiguration; +import org.apache.qpid.server.logging.RootMessageLogger; +import org.apache.qpid.server.logging.actors.CurrentActor; +import org.apache.qpid.server.logging.messages.BrokerMessages; import org.apache.qpid.server.management.ManagedObjectRegistry; import org.apache.qpid.server.plugins.PluginManager; import org.apache.qpid.server.security.access.ACLManager; import org.apache.qpid.server.security.auth.database.PrincipalDatabaseManager; import org.apache.qpid.server.security.auth.manager.AuthenticationManager; +import org.apache.qpid.server.transport.QpidAcceptor; import org.apache.qpid.server.virtualhost.VirtualHost; +import org.apache.qpid.server.virtualhost.VirtualHostImpl; import org.apache.qpid.server.virtualhost.VirtualHostRegistry; -import org.apache.qpid.server.logging.RootMessageLogger; -import org.apache.qpid.server.logging.messages.BrokerMessages; -import org.apache.qpid.server.logging.actors.CurrentActor; -import org.apache.qpid.server.transport.QpidAcceptor; + +import java.net.InetSocketAddress; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; /** * An abstract application registry that provides access to configuration information and handles the @@ -75,6 +84,14 @@ public abstract class ApplicationRegistry implements IApplicationRegistry protected RootMessageLogger _rootMessageLogger; + protected UUID _brokerId = UUID.randomUUID(); + + protected QMFService _qmfService; + + private BrokerConfig _broker; + + private ConfigStore _configStore; + static { Runtime.getRuntime().addShutdownHook(new Thread(new ShutdownService())); @@ -100,6 +117,16 @@ public abstract class ApplicationRegistry implements IApplicationRegistry _logger.info("Initialising Application Registry:" + instanceID); _instanceMap.put(instanceID, instance); + final ConfigStore store = ConfigStore.newInstance(); + store.setRoot(new SystemConfigImpl(store)); + instance.setConfigStore(store); + + BrokerConfig broker = new BrokerConfigAdapter(instance, instanceID); + + SystemConfig system = (SystemConfig) store.getRoot(); + system.addBroker(broker); + instance.setBroker(broker); + try { instance.initialise(instanceID); @@ -107,7 +134,14 @@ public abstract class ApplicationRegistry implements IApplicationRegistry catch (Exception e) { _instanceMap.remove(instanceID); - throw e; + try + { + system.removeBroker(broker); + } + finally + { + throw e; + } } } else @@ -116,6 +150,16 @@ public abstract class ApplicationRegistry implements IApplicationRegistry } } + public ConfigStore getConfigStore() + { + return _configStore; + } + + public void setConfigStore(final ConfigStore configStore) + { + _configStore = configStore; + } + public static boolean isConfigured() { return isConfigured(DEFAULT_INSTANCE); @@ -151,6 +195,7 @@ public abstract class ApplicationRegistry implements IApplicationRegistry _logger.info("Shuting down ApplicationRegistry(" + instanceID + "):" + instance); } instance.close(); + instance.getBroker().getSystem().removeBroker(instance.getBroker()); } } catch (Exception e) @@ -316,5 +361,32 @@ public abstract class ApplicationRegistry implements IApplicationRegistry { return _rootMessageLogger; } - + + public UUID getBrokerId() + { + return _brokerId; + } + + public QMFService getQMFService() + { + return _qmfService; + } + + public BrokerConfig getBroker() + { + return _broker; + } + + public void setBroker(final BrokerConfig broker) + { + _broker = broker; + } + + public VirtualHost createVirtualHost(final VirtualHostConfiguration vhostConfig) throws Exception + { + VirtualHostImpl virtualHost = new VirtualHostImpl(this, vhostConfig); + _virtualHostRegistry.registerVirtualHost(virtualHost); + getBroker().addVirtualHost(virtualHost); + return virtualHost; + } } diff --git a/java/broker/src/main/java/org/apache/qpid/server/registry/BrokerConfigAdapter.java b/java/broker/src/main/java/org/apache/qpid/server/registry/BrokerConfigAdapter.java new file mode 100644 index 0000000000..c3d1945550 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/registry/BrokerConfigAdapter.java @@ -0,0 +1,163 @@ +/* + * + * 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.registry; + +import org.apache.qpid.server.configuration.*; +import org.apache.qpid.server.virtualhost.VirtualHost; +import org.apache.qpid.common.QpidProperties; + +import java.util.UUID; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +public class BrokerConfigAdapter implements BrokerConfig +{ + private final IApplicationRegistry _instance; + private final int _instanceId; + private SystemConfig _system; + + private final Map<UUID, VirtualHostConfig> _vhosts = new ConcurrentHashMap<UUID, VirtualHostConfig>(); + private final long _createTime = System.currentTimeMillis(); + private UUID _id; + private String _federationTag; + + public BrokerConfigAdapter(final IApplicationRegistry instance, final int instanceID) + { + _instance = instance; + _instanceId = instanceID; + _id = instance.getConfigStore().createId(); + _federationTag = UUID.randomUUID().toString(); + } + + public void setSystem(final SystemConfig system) + { + _system = system; + } + + public SystemConfig getSystem() + { + return _system; + } + + public Integer getPort() + { + List ports = _instance.getConfiguration().getPorts(); + if(ports.size() > 0) + { + return Integer.valueOf(ports.get(0).toString()); + } + else + { + return 0; + } + } + + public Integer getWorkerThreads() + { + return _instance.getConfiguration().getProcessors(); + } + + public Integer getMaxConnections() + { + return 0; + } + + public Integer getConnectionBacklogLimit() + { + return 0; + } + + public Long getStagingThreshold() + { + return 0L; + } + + public Integer getManagementPublishInterval() + { + return 10; + } + + public String getVersion() + { + return QpidProperties.getReleaseVersion() + " [Build: " + QpidProperties.getBuildVersion() + "]"; + } + + public String getDataDirectory() + { + return _instance.getConfiguration().getQpidWork(); + } + + public void addVirtualHost(final VirtualHostConfig virtualHost) + { + virtualHost.setBroker(this); + _vhosts.put(virtualHost.getId(), virtualHost); + getConfigStore().addConfiguredObject(virtualHost); + + } + + private ConfigStore getConfigStore() + { + return _instance.getConfigStore(); + } + + public long getCreateTime() + { + return _createTime; + } + + public void createBrokerConnection(final String transport, + final String host, + final int port, + final boolean durable, + final String authMechanism, + final String username, + final String password) + { + VirtualHost vhost = _instance.getVirtualHostRegistry().getDefaultVirtualHost(); + vhost.createBrokerConnection(transport, host, port, "", durable, authMechanism, username, password); + } + + public UUID getId() + { + return _id; + } + + public BrokerConfigType getConfigType() + { + return BrokerConfigType.getInstance(); + } + + public ConfiguredObject getParent() + { + return _system; + } + + public boolean isDurable() + { + return false; + } + + public String getFederationTag() + { + return _federationTag; + } +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/registry/ConfigurationFileApplicationRegistry.java b/java/broker/src/main/java/org/apache/qpid/server/registry/ConfigurationFileApplicationRegistry.java index f325b53dfb..e1cc1bf1dd 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/registry/ConfigurationFileApplicationRegistry.java +++ b/java/broker/src/main/java/org/apache/qpid/server/registry/ConfigurationFileApplicationRegistry.java @@ -21,13 +21,15 @@ package org.apache.qpid.server.registry; import org.apache.commons.configuration.ConfigurationException; + import org.apache.qpid.AMQException; import org.apache.qpid.common.QpidProperties; +import org.apache.qpid.qmf.QMFService; import org.apache.qpid.server.configuration.ServerConfiguration; import org.apache.qpid.server.logging.RootMessageLoggerImpl; -import org.apache.qpid.server.logging.messages.BrokerMessages; -import org.apache.qpid.server.logging.actors.CurrentActor; import org.apache.qpid.server.logging.actors.BrokerActor; +import org.apache.qpid.server.logging.actors.CurrentActor; +import org.apache.qpid.server.logging.messages.BrokerMessages; import org.apache.qpid.server.logging.rawloggers.Log4jMessageLogger; import org.apache.qpid.server.management.JMXManagedObjectRegistry; import org.apache.qpid.server.management.NoopManagedObjectRegistry; @@ -36,7 +38,6 @@ import org.apache.qpid.server.security.access.ACLManager; import org.apache.qpid.server.security.auth.database.ConfigurationFilePrincipalDatabaseManager; import org.apache.qpid.server.security.auth.manager.PrincipalDatabaseAuthenticationManager; import org.apache.qpid.server.virtualhost.VirtualHostRegistry; -import org.apache.qpid.server.virtualhost.VirtualHostImpl; import java.io.File; @@ -51,6 +52,9 @@ public class ConfigurationFileApplicationRegistry extends ApplicationRegistry public void initialise(int instanceID) throws Exception { + _qmfService = new QMFService(getConfigStore(), this); + + _rootMessageLogger = new RootMessageLoggerImpl(_configuration, new Log4jMessageLogger()); @@ -75,6 +79,7 @@ public class ConfigurationFileApplicationRegistry extends ApplicationRegistry _databaseManager.initialiseManagement(_configuration); + _managedObjectRegistry.start(); initialiseVirtualHosts(); @@ -91,6 +96,7 @@ public class ConfigurationFileApplicationRegistry extends ApplicationRegistry try { super.close(); + _qmfService.close(); } finally { @@ -102,7 +108,7 @@ public class ConfigurationFileApplicationRegistry extends ApplicationRegistry { for (String name : _configuration.getVirtualHosts()) { - _virtualHostRegistry.registerVirtualHost(new VirtualHostImpl(_configuration.getVirtualHostConfig(name))); + createVirtualHost(_configuration.getVirtualHostConfig(name)); } getVirtualHostRegistry().setDefaultVirtualHostName(_configuration.getDefaultVirtualHost()); } diff --git a/java/broker/src/main/java/org/apache/qpid/server/registry/IApplicationRegistry.java b/java/broker/src/main/java/org/apache/qpid/server/registry/IApplicationRegistry.java index 92accb3499..f0226c7982 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/registry/IApplicationRegistry.java +++ b/java/broker/src/main/java/org/apache/qpid/server/registry/IApplicationRegistry.java @@ -7,9 +7,9 @@ * 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 @@ -20,22 +20,25 @@ */ package org.apache.qpid.server.registry; -import java.util.Collection; -import java.net.InetSocketAddress; - -import org.apache.commons.configuration.Configuration; import org.apache.commons.configuration.ConfigurationException; + +import org.apache.qpid.qmf.QMFService; +import org.apache.qpid.server.configuration.BrokerConfig; +import org.apache.qpid.server.configuration.ConfigStore; import org.apache.qpid.server.configuration.ServerConfiguration; +import org.apache.qpid.server.configuration.VirtualHostConfiguration; +import org.apache.qpid.server.logging.RootMessageLogger; import org.apache.qpid.server.management.ManagedObjectRegistry; import org.apache.qpid.server.plugins.PluginManager; -import org.apache.qpid.server.security.auth.manager.AuthenticationManager; -import org.apache.qpid.server.security.auth.database.PrincipalDatabaseManager; import org.apache.qpid.server.security.access.ACLManager; -import org.apache.qpid.server.security.access.ACLPlugin; -import org.apache.qpid.server.virtualhost.VirtualHostRegistry; -import org.apache.qpid.server.logging.RootMessageLogger; +import org.apache.qpid.server.security.auth.database.PrincipalDatabaseManager; +import org.apache.qpid.server.security.auth.manager.AuthenticationManager; import org.apache.qpid.server.transport.QpidAcceptor; -import org.apache.mina.common.IoAcceptor; +import org.apache.qpid.server.virtualhost.VirtualHost; +import org.apache.qpid.server.virtualhost.VirtualHostRegistry; + +import java.net.InetSocketAddress; +import java.util.UUID; public interface IApplicationRegistry { @@ -81,4 +84,17 @@ public interface IApplicationRegistry */ void addAcceptor(InetSocketAddress bindAddress, QpidAcceptor acceptor); + public UUID getBrokerId(); + + QMFService getQMFService(); + + void setBroker(BrokerConfig broker); + + BrokerConfig getBroker(); + + VirtualHost createVirtualHost(VirtualHostConfiguration vhostConfig) throws Exception; + + ConfigStore getConfigStore(); + + void setConfigStore(ConfigStore store); } diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/access/PrincipalPermissions.java b/java/broker/src/main/java/org/apache/qpid/server/security/access/PrincipalPermissions.java index a299907e42..e7fc8effaf 100755 --- a/java/broker/src/main/java/org/apache/qpid/server/security/access/PrincipalPermissions.java +++ b/java/broker/src/main/java/org/apache/qpid/server/security/access/PrincipalPermissions.java @@ -42,7 +42,7 @@ public class PrincipalPermissions private static final Object CREATE_QUEUES_KEY = new Object(); private static final Object CREATE_EXCHANGES_KEY = new Object(); - + private static final Object CREATE_QUEUE_TEMPORARY_KEY = new Object(); private static final Object CREATE_QUEUE_QUEUES_KEY = new Object(); private static final Object CREATE_QUEUE_EXCHANGES_KEY = new Object(); @@ -64,9 +64,9 @@ public class PrincipalPermissions } /** - * + * * @param permission the type of permission to check - * + * * @param parameters vararg depending on what permission was passed in * ACCESS: none * BIND: none @@ -113,7 +113,7 @@ public class PrincipalPermissions { _fullVHostAccess = true; } - + private void grantPublish(Permission permission, Object... parameters) { Map publishRights = (Map) _permissions.get(permission); @@ -344,9 +344,9 @@ public class PrincipalPermissions } /** - * + * * @param permission the type of permission to check - * + * * @param parameters vararg depending on what permission was passed in * ACCESS: none * BIND: QueueBindBody bindmethod, Exchange exchange, AMQQueue queue, AMQShortString routingKey @@ -363,7 +363,7 @@ public class PrincipalPermissions switch (permission) { - case ACCESS://No Parameters + case ACCESS://No Parameters return AuthzResult.ALLOWED; // The existence of this user-specific PP infers some level of access is authorised case BIND: // Parameters : QueueBindMethod , Exchange , AMQQueue, AMQShortString routingKey return authoriseBind(parameters); @@ -444,7 +444,7 @@ public class PrincipalPermissions { if ( new AMQShortString(queue.getPrincipalHolder().getPrincipal().getName()).equals(_user)) { - return (queues.size() == 0 || queues.contains(queue.getName())) ? AuthzResult.ALLOWED : AuthzResult.DENIED; + return (queues.size() == 0 || queues.contains(queue.getNameShortString())) ? AuthzResult.ALLOWED : AuthzResult.DENIED; } else { @@ -453,7 +453,7 @@ public class PrincipalPermissions } // If we are - return (queues.size() == 0 || queues.contains(queue.getName())) ? AuthzResult.ALLOWED : AuthzResult.DENIED; + return (queues.size() == 0 || queues.contains(queue.getNameShortString())) ? AuthzResult.ALLOWED : AuthzResult.DENIED; } } @@ -486,7 +486,7 @@ public class PrincipalPermissions // Otherwise exchange must be listed in the white list // If the map doesn't have the exchange then it isn't allowed - if (!exchanges.containsKey(((Exchange) parameters[0]).getName())) + if (!exchanges.containsKey(((Exchange) parameters[0]).getNameShortString())) { return AuthzResult.DENIED; } @@ -494,7 +494,7 @@ public class PrincipalPermissions { // Get valid routing keys - HashSet routingKeys = (HashSet) exchanges.get(((Exchange)parameters[0]).getName()); + HashSet routingKeys = (HashSet) exchanges.get(((Exchange)parameters[0]).getNameShortString()); // Having no routingKeys in the map then all are allowed. if (routingKeys == null) @@ -544,7 +544,7 @@ public class PrincipalPermissions // check the valid exchanges if (rights == null || rights.containsKey(exchangeName)) { - return AuthzResult.ALLOWED; + return AuthzResult.ALLOWED; } else { @@ -587,13 +587,13 @@ public class PrincipalPermissions // If there is a white list then check if (create_queues_queues == null || create_queues_queues.containsKey(queueName)) { - return AuthzResult.ALLOWED; + return AuthzResult.ALLOWED; } else { return AuthzResult.DENIED; } - + } } @@ -604,7 +604,7 @@ public class PrincipalPermissions //user has been granted full access to the vhost return AuthzResult.ALLOWED; } - + Exchange exchange = (Exchange) parameters[1]; AMQQueue bind_queueName = (AMQQueue) parameters[2]; @@ -631,7 +631,7 @@ public class PrincipalPermissions } // Check to see if we have a white list of routingkeys to check - Map rkeys = (Map) exchangeDetails.get(exchange.getName()); + Map rkeys = (Map) exchangeDetails.get(exchange.getNameShortString()); // if keys is null then any rkey is allowed on this exchange if (rkeys == null) diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/anonymous/AnonymousInitialiser.java b/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/anonymous/AnonymousInitialiser.java new file mode 100644 index 0000000000..4a66b74783 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/anonymous/AnonymousInitialiser.java @@ -0,0 +1,39 @@ +/* + * + * 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.auth.sasl.anonymous; + +import javax.security.sasl.SaslServerFactory; + +import org.apache.qpid.server.security.auth.sasl.UsernamePasswordInitialiser; +import org.apache.qpid.server.security.auth.sasl.amqplain.AmqPlainSaslServerFactory; + +public class AnonymousInitialiser extends UsernamePasswordInitialiser +{ + public String getMechanismName() + { + return "ANONYMOUS"; + } + + public Class<? extends SaslServerFactory> getServerFactoryClassForJCARegistration() + { + return AnonymousSaslServerFactory.class; + } +}
\ No newline at end of file diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/anonymous/AnonymousSaslServer.java b/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/anonymous/AnonymousSaslServer.java new file mode 100644 index 0000000000..b4cce15d88 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/anonymous/AnonymousSaslServer.java @@ -0,0 +1,88 @@ +/* + * + * 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.auth.sasl.anonymous; + +import java.io.IOException; + +import javax.security.auth.callback.Callback; +import javax.security.auth.callback.CallbackHandler; +import javax.security.auth.callback.NameCallback; +import javax.security.auth.callback.PasswordCallback; +import javax.security.auth.callback.UnsupportedCallbackException; +import javax.security.sasl.AuthorizeCallback; +import javax.security.sasl.SaslException; +import javax.security.sasl.SaslServer; + +import org.apache.mina.common.ByteBuffer; +import org.apache.qpid.framing.AMQFrameDecodingException; +import org.apache.qpid.framing.FieldTable; +import org.apache.qpid.framing.FieldTableFactory; + +public class AnonymousSaslServer implements SaslServer +{ + public static final String MECHANISM = "ANONYMOUS"; + + private boolean _complete = false; + + public AnonymousSaslServer() + { + } + + public String getMechanismName() + { + return MECHANISM; + } + + public byte[] evaluateResponse(byte[] response) throws SaslException + { + _complete = true; + return null; + } + + public boolean isComplete() + { + return _complete; + } + + public String getAuthorizationID() + { + return null; + } + + public byte[] unwrap(byte[] incoming, int offset, int len) throws SaslException + { + throw new SaslException("Unsupported operation"); + } + + public byte[] wrap(byte[] outgoing, int offset, int len) throws SaslException + { + throw new SaslException("Unsupported operation"); + } + + public Object getNegotiatedProperty(String propName) + { + return null; + } + + public void dispose() throws SaslException + { + } +}
\ No newline at end of file diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/anonymous/AnonymousSaslServerFactory.java b/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/anonymous/AnonymousSaslServerFactory.java new file mode 100644 index 0000000000..6032255870 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/anonymous/AnonymousSaslServerFactory.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.server.security.auth.sasl.anonymous; + +import org.apache.qpid.server.security.auth.sasl.amqplain.AmqPlainSaslServer; + +import java.util.Map; + +import javax.security.auth.callback.CallbackHandler; +import javax.security.sasl.Sasl; +import javax.security.sasl.SaslException; +import javax.security.sasl.SaslServer; +import javax.security.sasl.SaslServerFactory; + +public class AnonymousSaslServerFactory implements SaslServerFactory +{ + public SaslServer createSaslServer(String mechanism, String protocol, String serverName, Map props, + CallbackHandler cbh) throws SaslException + { + if (AnonymousSaslServer.MECHANISM.equals(mechanism)) + { + return new AnonymousSaslServer(); + } + else + { + return null; + } + } + + public String[] getMechanismNames(Map props) + { + if (props.containsKey(Sasl.POLICY_NOPLAINTEXT) || + props.containsKey(Sasl.POLICY_NODICTIONARY) || + props.containsKey(Sasl.POLICY_NOACTIVE) || + props.containsKey(Sasl.POLICY_NOANONYMOUS)) + { + // returned array must be non null according to interface documentation + return new String[0]; + } + else + { + return new String[]{AnonymousSaslServer.MECHANISM}; + } + } +}
\ No newline at end of file diff --git a/java/broker/src/main/java/org/apache/qpid/server/store/DerbyMessageStore.java b/java/broker/src/main/java/org/apache/qpid/server/store/DerbyMessageStore.java index 5ca75aa9ae..31211d6b9e 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/store/DerbyMessageStore.java +++ b/java/broker/src/main/java/org/apache/qpid/server/store/DerbyMessageStore.java @@ -20,22 +20,24 @@ */ package org.apache.qpid.server.store; +import org.apache.commons.configuration.Configuration; import org.apache.log4j.Logger; + import org.apache.qpid.AMQException; import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.framing.FieldTable; import org.apache.qpid.server.exchange.Exchange; +import org.apache.qpid.server.logging.LogSubject; import org.apache.qpid.server.logging.actors.CurrentActor; -import org.apache.qpid.server.logging.messages.MessageStoreMessages; import org.apache.qpid.server.logging.messages.ConfigStoreMessages; +import org.apache.qpid.server.logging.messages.MessageStoreMessages; import org.apache.qpid.server.logging.messages.TransactionLogMessages; -import org.apache.qpid.server.logging.LogSubject; import org.apache.qpid.server.queue.AMQQueue; -import org.apache.commons.configuration.Configuration; - import java.io.ByteArrayInputStream; import java.io.File; +import java.lang.ref.WeakReference; +import java.nio.ByteBuffer; import java.sql.Blob; import java.sql.Connection; import java.sql.Driver; @@ -49,8 +51,6 @@ import java.util.ArrayList; import java.util.List; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicLong; -import java.lang.ref.WeakReference; -import java.nio.ByteBuffer; public class DerbyMessageStore implements MessageStore @@ -590,7 +590,10 @@ public class DerbyMessageStore implements MessageStore conn = newConnection(); PreparedStatement stmt = conn.prepareStatement(FIND_EXCHANGE); - stmt.setString(1, exchange.getName().toString()); + stmt.setString(1, exchange.getNameShortString().toString()); + stmt.execute(); + stmt.close(); + conn.commit(); ResultSet rs = stmt.executeQuery(); @@ -617,7 +620,7 @@ public class DerbyMessageStore implements MessageStore } catch (SQLException e) { - throw new AMQException("Error writing Exchange with name " + exchange.getName() + " to database: " + e, e); + throw new AMQException("Error writing Exchange with name " + exchange.getNameShortString() + " to database: " + e, e); } } @@ -631,11 +634,11 @@ public class DerbyMessageStore implements MessageStore { conn = newConnection(); PreparedStatement stmt = conn.prepareStatement(DELETE_FROM_EXCHANGE); - stmt.setString(1, exchange.getName().toString()); + stmt.setString(1, exchange.getNameShortString().toString()); int results = stmt.executeUpdate(); if(results == 0) { - throw new AMQException("Exchange " + exchange.getName() + " not found"); + throw new AMQException("Exchange " + exchange.getNameShortString() + " not found"); } else { @@ -645,7 +648,7 @@ public class DerbyMessageStore implements MessageStore } catch (SQLException e) { - throw new AMQException("Error writing deleting with name " + exchange.getName() + " from database: " + e, e); + throw new AMQException("Error writing deleting with name " + exchange.getNameShortString() + " from database: " + e, e); } finally { @@ -677,8 +680,8 @@ public class DerbyMessageStore implements MessageStore conn = newConnection(); PreparedStatement stmt = conn.prepareStatement(FIND_BINDING); - stmt.setString(1, exchange.getName().toString() ); - stmt.setString(2, queue.getName().toString()); + stmt.setString(1, exchange.getNameShortString().toString() ); + stmt.setString(2, queue.getNameShortString().toString()); stmt.setString(3, routingKey == null ? null : routingKey.toString()); ResultSet rs = stmt.executeQuery(); @@ -687,8 +690,8 @@ public class DerbyMessageStore implements MessageStore if (!rs.next()) { stmt = conn.prepareStatement(INSERT_INTO_BINDINGS); - stmt.setString(1, exchange.getName().toString() ); - stmt.setString(2, queue.getName().toString()); + stmt.setString(1, exchange.getNameShortString().toString() ); + stmt.setString(2, queue.getNameShortString().toString()); stmt.setString(3, routingKey == null ? null : routingKey.toString()); if(args != null) { @@ -713,8 +716,8 @@ public class DerbyMessageStore implements MessageStore } catch (SQLException e) { - throw new AMQException("Error writing binding for AMQQueue with name " + queue.getName() + " to exchange " - + exchange.getName() + " to database: " + e, e); + throw new AMQException("Error writing binding for AMQQueue with name " + queue.getNameShortString() + " to exchange " + + exchange.getNameShortString() + " to database: " + e, e); } finally { @@ -748,23 +751,23 @@ public class DerbyMessageStore implements MessageStore conn = newConnection(); // exchange_name varchar(255) not null, queue_name varchar(255) not null, binding_key varchar(255), arguments blob PreparedStatement stmt = conn.prepareStatement(DELETE_FROM_BINDINGS); - stmt.setString(1, exchange.getName().toString() ); - stmt.setString(2, queue.getName().toString()); + stmt.setString(1, exchange.getNameShortString().toString() ); + stmt.setString(2, queue.getNameShortString().toString()); stmt.setString(3, routingKey == null ? null : routingKey.toString()); if(stmt.executeUpdate() != 1) { - throw new AMQException("Queue binding for queue with name " + queue.getName() + " to exchange " - + exchange.getName() + " not found"); + throw new AMQException("Queue binding for queue with name " + queue.getNameShortString() + " to exchange " + + exchange.getNameShortString() + " not found"); } conn.commit(); stmt.close(); } catch (SQLException e) { - throw new AMQException("Error removing binding for AMQQueue with name " + queue.getName() + " to exchange " - + exchange.getName() + " in database: " + e, e); + throw new AMQException("Error removing binding for AMQQueue with name " + queue.getNameShortString() + " to exchange " + + exchange.getNameShortString() + " in database: " + e, e); } finally { @@ -801,7 +804,7 @@ public class DerbyMessageStore implements MessageStore Connection conn = newConnection(); PreparedStatement stmt = conn.prepareStatement(FIND_QUEUE); - stmt.setString(1, queue.getName().toString()); + stmt.setString(1, queue.getNameShortString().toString()); ResultSet rs = stmt.executeQuery(); @@ -816,7 +819,7 @@ public class DerbyMessageStore implements MessageStore ? null : queue.getPrincipalHolder().getPrincipal().getName(); - stmt.setString(1, queue.getName().toString()); + stmt.setString(1, queue.getNameShortString().toString()); stmt.setString(2, owner); stmt.execute(); @@ -830,7 +833,7 @@ public class DerbyMessageStore implements MessageStore } catch (SQLException e) { - throw new AMQException("Error writing AMQQueue with name " + queue.getName() + " to database: " + e, e); + throw new AMQException("Error writing AMQQueue with name " + queue.getNameShortString() + " to database: " + e, e); } } } @@ -843,7 +846,7 @@ public class DerbyMessageStore implements MessageStore public void removeQueue(final AMQQueue queue) throws AMQException { - AMQShortString name = queue.getName(); + AMQShortString name = queue.getNameShortString(); _logger.debug("public void removeQueue(AMQShortString name = " + name + "): called"); Connection conn = null; diff --git a/java/broker/src/main/java/org/apache/qpid/server/store/DurableConfigurationStore.java b/java/broker/src/main/java/org/apache/qpid/server/store/DurableConfigurationStore.java index cfbacd28c8..a50e8e99b4 100755 --- a/java/broker/src/main/java/org/apache/qpid/server/store/DurableConfigurationStore.java +++ b/java/broker/src/main/java/org/apache/qpid/server/store/DurableConfigurationStore.java @@ -31,6 +31,11 @@ import org.apache.commons.configuration.Configuration; public interface DurableConfigurationStore { + public static interface Source + { + DurableConfigurationStore getDurableConfigurationStore(); + } + /** * Called after instantiation in order to configure the message store. A particular implementation can define * whatever parameters it wants. diff --git a/java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionImpl.java b/java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionImpl.java index 684d3c2e74..b0ea0ef506 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionImpl.java +++ b/java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionImpl.java @@ -20,41 +20,49 @@ */ package org.apache.qpid.server.subscription; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicReference; -import java.util.concurrent.atomic.AtomicLong; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantLock; -import java.util.concurrent.ConcurrentHashMap; -import java.util.Map; - import org.apache.log4j.Logger; + import org.apache.qpid.AMQException; import org.apache.qpid.common.AMQPFilterTypes; import org.apache.qpid.common.ClientProperties; import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.framing.FieldTable; import org.apache.qpid.server.AMQChannel; -import org.apache.qpid.server.message.AMQMessage; -import org.apache.qpid.server.output.ProtocolOutputConverter; +import org.apache.qpid.server.configuration.ConfigStore; +import org.apache.qpid.server.configuration.ConfiguredObject; +import org.apache.qpid.server.configuration.SessionConfig; +import org.apache.qpid.server.configuration.SubscriptionConfig; +import org.apache.qpid.server.configuration.SubscriptionConfigType; +import org.apache.qpid.server.filter.FilterManager; +import org.apache.qpid.server.filter.FilterManagerFactory; +import org.apache.qpid.server.flow.FlowCreditManager; +import org.apache.qpid.server.logging.LogActor; +import org.apache.qpid.server.logging.LogSubject; import org.apache.qpid.server.logging.actors.CurrentActor; import org.apache.qpid.server.logging.actors.SubscriptionActor; import org.apache.qpid.server.logging.messages.SubscriptionMessages; import org.apache.qpid.server.logging.subjects.SubscriptionLogSubject; -import org.apache.qpid.server.logging.LogSubject; -import org.apache.qpid.server.logging.LogActor; -import org.apache.qpid.server.queue.QueueEntry; -import org.apache.qpid.server.queue.AMQQueue; -import org.apache.qpid.server.flow.FlowCreditManager; -import org.apache.qpid.server.filter.FilterManager; -import org.apache.qpid.server.filter.FilterManagerFactory; +import org.apache.qpid.server.message.AMQMessage; +import org.apache.qpid.server.output.ProtocolOutputConverter; import org.apache.qpid.server.protocol.AMQProtocolSession; +import org.apache.qpid.server.queue.AMQQueue; +import org.apache.qpid.server.queue.QueueEntry; + +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.atomic.AtomicReference; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; /** * Encapsulation of a supscription to a queue. <p/> Ties together the protocol session of a subscriber, the consumer tag * that was given out by the broker and the channel id. <p/> */ -public abstract class SubscriptionImpl implements Subscription, FlowCreditManager.FlowCreditManagerListener +public abstract class SubscriptionImpl implements Subscription, FlowCreditManager.FlowCreditManagerListener, + SubscriptionConfig { private StateListener _stateListener = new StateListener() @@ -85,6 +93,7 @@ public abstract class SubscriptionImpl implements Subscription, FlowCreditManage private final long _subscriptionID = idGenerator.getAndIncrement(); private LogSubject _logSubject; private LogActor _logActor; + private UUID _id; static final class BrowserSubscription extends SubscriptionImpl @@ -152,6 +161,12 @@ public abstract class SubscriptionImpl implements Subscription, FlowCreditManage return false; } + @Override + public boolean isExplicitAcknowledge() + { + return false; + } + /** * This method can be called by each of the publisher threads. As a result all changes to the channel object must be * thread safe. @@ -318,9 +333,12 @@ public abstract class SubscriptionImpl implements Subscription, FlowCreditManage _autoClose = false; } - } + public ConfigStore getConfigStore() + { + return getQueue().getConfigStore(); + } public synchronized void setQueue(AMQQueue queue, boolean exclusive) @@ -331,6 +349,9 @@ public abstract class SubscriptionImpl implements Subscription, FlowCreditManage } _queue = queue; + _id = getConfigStore().createId(); + getConfigStore().addConfiguredObject(this); + _logSubject = new SubscriptionLogSubject(this); _logActor = new SubscriptionActor(CurrentActor.get().getRootMessageLogger(), this); @@ -414,7 +435,7 @@ public abstract class SubscriptionImpl implements Subscription, FlowCreditManage public boolean hasInterest(QueueEntry entry) { - + //check that the message hasn't been rejected @@ -505,7 +526,7 @@ public abstract class SubscriptionImpl implements Subscription, FlowCreditManage { _stateChangeLock.unlock(); } - + getConfigStore().removeConfiguredObject(this); //Log Subscription closed CurrentActor.get().message(_logSubject, SubscriptionMessages.SUB_CLOSE()); @@ -689,4 +710,60 @@ public abstract class SubscriptionImpl implements Subscription, FlowCreditManage } abstract boolean isBrowser(); + + public String getCreditMode() + { + return "WINDOW"; + } + + public SessionConfig getSessionConfig() + { + return getChannel(); + } + + public boolean isBrowsing() + { + return isBrowser(); + } + + public boolean isExplicitAcknowledge() + { + return true; + } + + public UUID getId() + { + return _id; + } + + public boolean isDurable() + { + return false; + } + + public SubscriptionConfigType getConfigType() + { + return SubscriptionConfigType.getInstance(); + } + + public boolean isExclusive() + { + return getQueue().hasExclusiveSubscriber(); + } + + public ConfiguredObject getParent() + { + return getSessionConfig(); + } + + public String getName() + { + return String.valueOf(_consumerTag); + } + + public Map<String, Object> getArguments() + { + return null; + } + } diff --git a/java/broker/src/main/java/org/apache/qpid/server/subscription/Subscription_0_10.java b/java/broker/src/main/java/org/apache/qpid/server/subscription/Subscription_0_10.java index 5b3668ab64..54c294c76d 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/subscription/Subscription_0_10.java +++ b/java/broker/src/main/java/org/apache/qpid/server/subscription/Subscription_0_10.java @@ -36,11 +36,12 @@ import org.apache.qpid.server.message.ServerMessage; import org.apache.qpid.server.message.MessageTransferMessage; import org.apache.qpid.server.message.AMQMessage; import org.apache.qpid.server.transport.ServerSession; +import org.apache.qpid.server.configuration.*; +import org.apache.qpid.server.txn.ServerTransaction; +import org.apache.qpid.server.txn.AutoCommitTransaction; import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.framing.ContentHeaderProperties; import org.apache.qpid.framing.BasicContentHeaderProperties; import org.apache.qpid.framing.FieldTable; -import org.apache.qpid.framing.AMQTypedValue; import org.apache.qpid.AMQException; import org.apache.qpid.transport.*; @@ -50,12 +51,10 @@ import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.ConcurrentHashMap; -import java.util.ArrayList; -import java.util.Map; -import java.util.HashMap; +import java.util.*; import java.nio.ByteBuffer; -public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCreditManagerListener +public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCreditManagerListener, SubscriptionConfig { private static final AtomicLong idGenerator = new AtomicLong(0); @@ -98,6 +97,9 @@ public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCr private LogSubject _logSubject; private LogActor _logActor; private Map<String, Object> _properties = new ConcurrentHashMap<String, Object>(); + private UUID _id; + private String _traceExclude; + private String _trace; public Subscription_0_10(ServerSession session, String destination, MessageAcceptMode acceptMode, @@ -116,7 +118,6 @@ public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCr _creditManager.addStateListener(this); _state.set(_creditManager.hasCredit() ? State.ACTIVE : State.SUSPENDED); - } public void setNoLocal(boolean noLocal) @@ -146,6 +147,11 @@ public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCr throw new IllegalStateException("Attempt to set queue for subscription " + this + " to " + queue + "when already set to " + getQueue()); } _queue = queue; + Map<String, Object> arguments = queue.getArguments() == null ? Collections.EMPTY_MAP : queue.getArguments(); + _traceExclude = (String) arguments.get("qpid.trace.exclude"); + _trace = (String) arguments.get("qpid.trace.id"); + _id = getConfigStore().createId(); + getConfigStore().addConfiguredObject(this); _logSubject = new SubscriptionLogSubject(this); _logActor = new SubscriptionActor(CurrentActor.get().getRootMessageLogger(), this); @@ -235,6 +241,7 @@ public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCr } } _creditManager.removeListener(this); + getConfigStore().removeConfiguredObject(this); } finally { @@ -245,6 +252,11 @@ public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCr } + public ConfigStore getConfigStore() + { + return getQueue().getConfigStore(); + } + public void creditStateChanged(boolean hasCredit) { @@ -290,6 +302,9 @@ public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCr MessageTransfer xfr; + DeliveryProperties deliveryProps; + MessageProperties messageProps = null; + if(serverMsg instanceof MessageTransferMessage) { @@ -316,11 +331,15 @@ public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCr } else { + if(header instanceof MessageProperties) + { + messageProps = (MessageProperties) header; + } newHeaders.add(header); } } - DeliveryProperties deliveryProps = new DeliveryProperties(); + deliveryProps = new DeliveryProperties(); if(origDeliveryProps != null) { if(origDeliveryProps.hasDeliveryMode()) @@ -343,21 +362,33 @@ public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCr { deliveryProps.setRoutingKey(origDeliveryProps.getRoutingKey()); } + if(origDeliveryProps.hasTimestamp()) + { + deliveryProps.setTimestamp(origDeliveryProps.getTimestamp()); + } + } deliveryProps.setRedelivered(entry.isRedelivered()); newHeaders.add(deliveryProps); + + if(_trace != null && messageProps == null) + { + messageProps = new MessageProperties(); + newHeaders.add(messageProps); + } + Header header = new Header(newHeaders); xfr = new MessageTransfer(_destination,_acceptMode,_acquireMode,header,msg.getBody()); } - else + else if(serverMsg instanceof AMQMessage) { AMQMessage message_0_8 = (AMQMessage) serverMsg; - DeliveryProperties deliveryProps = new DeliveryProperties(); - MessageProperties messageProps = new MessageProperties(); + deliveryProps = new DeliveryProperties(); + messageProps = new MessageProperties(); int size = (int) message_0_8.getSize(); ByteBuffer body = ByteBuffer.allocate(size); @@ -399,9 +430,52 @@ public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCr messageProps.setUserId(properties.getUserId().getBytes()); } + FieldTable fieldTable = properties.getHeaders(); + + final Map<String, Object> appHeaders = FieldTable.convertToMap(fieldTable); + + + messageProps.setApplicationHeaders(appHeaders); + + Header header = new Header(headers); + xfr = new MessageTransfer(_destination,_acceptMode,_acquireMode,header, body); + } + else + { + + deliveryProps = new DeliveryProperties(); + messageProps = new MessageProperties(); + + int size = (int) serverMsg.getSize(); + ByteBuffer body = ByteBuffer.allocate(size); + serverMsg.getContent(body, 0); + body.flip(); + + Struct[] headers = new Struct[] { deliveryProps, messageProps }; + + + deliveryProps.setExpiration(serverMsg.getExpiration()); + deliveryProps.setImmediate(serverMsg.isImmediate()); + deliveryProps.setPriority(MessageDeliveryPriority.get(serverMsg.getMessageHeader().getPriority())); + deliveryProps.setRedelivered(entry.isRedelivered()); + deliveryProps.setRoutingKey(serverMsg.getRoutingKey()); + deliveryProps.setTimestamp(serverMsg.getMessageHeader().getTimestamp()); + + messageProps.setContentEncoding(serverMsg.getMessageHeader().getEncoding()); + messageProps.setContentLength(size); + messageProps.setContentType(serverMsg.getMessageHeader().getMimeType()); + if(serverMsg.getMessageHeader().getCorrelationId() != null) + { + messageProps.setCorrelationId(serverMsg.getMessageHeader().getCorrelationId().getBytes()); + } + + + // TODO - ReplyTo + + final Map<String, Object> appHeaders = new HashMap<String, Object>(); - properties.getHeaders().processOverElements( + /*properties.getHeaders().processOverElements( new FieldTable.FieldTableElementProcessor() { @@ -424,39 +498,98 @@ public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCr messageProps.setApplicationHeaders(appHeaders); - +*/ Header header = new Header(headers); xfr = new MessageTransfer(_destination,_acceptMode,_acquireMode,header, body); } - if(_acceptMode == MessageAcceptMode.NONE) + boolean excludeDueToFederation = false; + + if(_trace != null) { - xfr.setCompletionListener(new MessageAcceptCompletionListener(this, _session, entry, _flowMode == MessageFlowMode.WINDOW)); + if(!messageProps.hasApplicationHeaders()) + { + messageProps.setApplicationHeaders(new HashMap<String,Object>()); + } + Map<String,Object> appHeaders = messageProps.getApplicationHeaders(); + String trace = (String) appHeaders.get("x-qpid.trace"); + if(trace == null) + { + trace = _trace; + } + else + { + if(_traceExclude != null) + { + excludeDueToFederation = Arrays.asList(trace.split(",")).contains(_traceExclude); + } + trace+=","+_trace; + } + appHeaders.put("x-qpid.trace",trace); } - else if(_flowMode == MessageFlowMode.WINDOW) + + if(!excludeDueToFederation) { - xfr.setCompletionListener(new Method.CompletionListener() - { - public void onComplete(Method method) + if(_acceptMode == MessageAcceptMode.NONE) + { + xfr.setCompletionListener(new MessageAcceptCompletionListener(this, _session, entry, _flowMode == MessageFlowMode.WINDOW)); + } + else if(_flowMode == MessageFlowMode.WINDOW) + { + xfr.setCompletionListener(new Method.CompletionListener() { - restoreCredit(entry); - } - }); - } + public void onComplete(Method method) + { + restoreCredit(entry); + } + }); + } - _postIdSettingAction._xfr = xfr; - if(_acceptMode == MessageAcceptMode.EXPLICIT) - { - _postIdSettingAction._action = new ExplicitAcceptDispositionChangeListener(entry, this); + _postIdSettingAction._xfr = xfr; + if(_acceptMode == MessageAcceptMode.EXPLICIT) + { + _postIdSettingAction._action = new ExplicitAcceptDispositionChangeListener(entry, this); + } + else + { + _postIdSettingAction._action = new ImplicitAcceptDispositionChangeListener(entry, this); + } + + _session.sendMessage(xfr, _postIdSettingAction); + + if(_acceptMode == MessageAcceptMode.NONE && _acquireMode == MessageAcquireMode.PRE_ACQUIRED) + { + forceDequeue(entry, false); + } } else { - _postIdSettingAction._action = new ImplicitAcceptDispositionChangeListener(entry, this); + forceDequeue(entry, _flowMode == MessageFlowMode.WINDOW); + } + } + + private void forceDequeue(final QueueEntry entry, final boolean restoreCredit) + { + ServerTransaction txn = new AutoCommitTransaction(getQueue().getVirtualHost().getTransactionLog()); + txn.dequeue(entry.getQueue(),entry.getMessage(), + new ServerTransaction.Action() + { + public void postCommit() + { + if(restoreCredit) + { + restoreCredit(entry); + } + entry.discard(); + } - _session.sendMessage(xfr, _postIdSettingAction); + public void onRollback() + { + } + }); } void reject(QueueEntry entry) @@ -660,4 +793,59 @@ public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCr } + public SessionConfig getSessionConfig() + { + return getSession(); + } + + public boolean isBrowsing() + { + return _acquireMode == MessageAcquireMode.NOT_ACQUIRED; + } + + public boolean isExclusive() + { + return getQueue().hasExclusiveSubscriber(); + } + + public ConfiguredObject getParent() + { + return getSessionConfig(); + } + + public boolean isDurable() + { + return false; + } + + public SubscriptionConfigType getConfigType() + { + return SubscriptionConfigType.getInstance(); + } + + public boolean isExplicitAcknowledge() + { + return _acceptMode == MessageAcceptMode.EXPLICIT; + } + + public String getCreditMode() + { + return _flowMode.toString(); + } + + public UUID getId() + { + return _id; + } + + public String getName() + { + return _destination; + } + + public Map<String, Object> getArguments() + { + //TODO + return Collections.EMPTY_MAP; + } } diff --git a/java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnection.java b/java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnection.java index 2a8b99ddac..1aff1eec86 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnection.java +++ b/java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnection.java @@ -20,12 +20,20 @@ */ package org.apache.qpid.server.transport; +import org.apache.qpid.server.configuration.ConnectionConfig; +import org.apache.qpid.server.virtualhost.VirtualHost; import org.apache.qpid.transport.Connection; import org.apache.qpid.transport.Method; -import org.apache.qpid.server.virtualhost.VirtualHost; public class ServerConnection extends Connection { + private ConnectionConfig _config; + private Runnable _onOpenTask; + + public ServerConnection() + { + } + @Override protected void invoke(Method method) { @@ -36,6 +44,10 @@ public class ServerConnection extends Connection protected void setState(State state) { super.setState(state); + if(state == State.OPEN && _onOpenTask != null) + { + _onOpenTask.run(); + } } @Override @@ -61,4 +73,19 @@ public class ServerConnection extends Connection { _virtualHost = virtualHost; } + + public void setConnectionConfig(final ConnectionConfig config) + { + _config = config; + } + + public ConnectionConfig getConfig() + { + return _config; + } + + public void onOpen(final Runnable task) + { + _onOpenTask = task; + } } diff --git a/java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnectionDelegate.java b/java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnectionDelegate.java index cfc5bb3a72..4cfcafa533 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnectionDelegate.java +++ b/java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnectionDelegate.java @@ -40,7 +40,7 @@ public class ServerConnectionDelegate extends ServerDelegate public ServerConnectionDelegate(IApplicationRegistry appRegistry, String localFQDN) { - this(Collections.EMPTY_MAP, Collections.singletonList((Object)"en_US"), appRegistry, localFQDN); + this(new HashMap<String,Object>(Collections.singletonMap("qpid.federation_tag",appRegistry.getBroker().getFederationTag())), Collections.singletonList((Object)"en_US"), appRegistry, localFQDN); } diff --git a/java/broker/src/main/java/org/apache/qpid/server/transport/ServerSession.java b/java/broker/src/main/java/org/apache/qpid/server/transport/ServerSession.java index 77dfbc0376..3e48ac2619 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/transport/ServerSession.java +++ b/java/broker/src/main/java/org/apache/qpid/server/transport/ServerSession.java @@ -20,32 +20,55 @@ */ package org.apache.qpid.server.transport; -import org.apache.qpid.transport.*; +import com.sun.security.auth.UserPrincipal; + +import org.apache.qpid.AMQException; +import org.apache.qpid.server.configuration.ConfigStore; +import org.apache.qpid.server.configuration.ConfiguredObject; +import org.apache.qpid.server.configuration.ConnectionConfig; +import org.apache.qpid.server.configuration.SessionConfig; +import org.apache.qpid.server.configuration.SessionConfigType; import org.apache.qpid.server.message.ServerMessage; import org.apache.qpid.server.queue.AMQQueue; +import org.apache.qpid.server.queue.BaseQueue; import org.apache.qpid.server.queue.QueueEntry; +import org.apache.qpid.server.security.PrincipalHolder; +import org.apache.qpid.server.store.MessageStore; import org.apache.qpid.server.subscription.Subscription_0_10; -import org.apache.qpid.server.txn.ServerTransaction; import org.apache.qpid.server.txn.AutoCommitTransaction; import org.apache.qpid.server.txn.LocalTransaction; -import org.apache.qpid.server.security.PrincipalHolder; -import org.apache.qpid.server.store.MessageStore; -import org.apache.qpid.AMQException; +import org.apache.qpid.server.txn.ServerTransaction; +import org.apache.qpid.server.virtualhost.VirtualHost; +import org.apache.qpid.transport.Binary; +import org.apache.qpid.transport.Connection; +import org.apache.qpid.transport.MessageTransfer; +import org.apache.qpid.transport.Method; +import org.apache.qpid.transport.Range; +import org.apache.qpid.transport.RangeSet; +import org.apache.qpid.transport.Session; +import org.apache.qpid.transport.SessionDelegate; +import static org.apache.qpid.util.Serial.gt; -import java.util.*; +import java.lang.ref.WeakReference; +import java.security.Principal; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.SortedMap; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentSkipListMap; import java.util.concurrent.CopyOnWriteArrayList; -import java.util.concurrent.ConcurrentHashMap; -import java.security.Principal; -import java.lang.ref.WeakReference; -import static org.apache.qpid.util.Serial.*; -import com.sun.security.auth.UserPrincipal; - -public class ServerSession extends Session implements PrincipalHolder +public class ServerSession extends Session implements PrincipalHolder, SessionConfig { private static final String NULL_DESTINTATION = UUID.randomUUID().toString(); + private final UUID _id; + private ConnectionConfig _connectionConfig; + public static interface MessageDispositionChangeListener { public void onAccept(); @@ -78,37 +101,41 @@ public class ServerSession extends Session implements PrincipalHolder private final WeakReference<Session> _reference; - - ServerSession(Connection connection, Binary name, long expiry) + ServerSession(Connection connection, SessionDelegate delegate, Binary name, long expiry) { - super(connection, name, expiry); - - _transaction = new AutoCommitTransaction(this.getMessageStore()); - _principal = new UserPrincipal(connection.getAuthorizationID()); - _reference = new WeakReference(this); + this(connection, delegate, name, expiry, ((ServerConnection)connection).getConfig()); } - ServerSession(Connection connection, SessionDelegate delegate, Binary name, long expiry) + public ServerSession(Connection connection, SessionDelegate delegate, Binary name, long expiry, ConnectionConfig connConfig) { super(connection, delegate, name, expiry); + _connectionConfig = connConfig; _transaction = new AutoCommitTransaction(this.getMessageStore()); _principal = new UserPrincipal(connection.getAuthorizationID()); _reference = new WeakReference(this); + _id = getConfigStore().createId(); + getConfigStore().addConfiguredObject(this); + } + + private ConfigStore getConfigStore() + { + return getConnectionConfig().getConfigStore(); } + @Override protected boolean isFull(int id) { return isCommandsFull(id); } - public void enqueue(final ServerMessage message, final ArrayList<AMQQueue> queues) + public void enqueue(final ServerMessage message, final ArrayList<? extends BaseQueue> queues) { _transaction.enqueue(queues,message, new ServerTransaction.Action() { - AMQQueue[] _queues = queues.toArray(new AMQQueue[queues.size()]); + BaseQueue[] _queues = queues.toArray(new BaseQueue[queues.size()]); public void postCommit() { @@ -243,7 +270,7 @@ public class ServerSession extends Session implements PrincipalHolder Iterator<Integer> unacceptedMessages = _messageDispositionListenerMap.keySet().iterator(); Iterator<Range> rangeIter = ranges.iterator(); - if(rangeIter.hasNext()) + if(rangeIter.hasNext()) { Range range = rangeIter.next(); @@ -290,6 +317,8 @@ public class ServerSession extends Session implements PrincipalHolder } _messageDispositionListenerMap.clear(); + getConfigStore().removeConfiguredObject(this); + for (Task task : _taskList) { task.doTask(this); @@ -391,8 +420,61 @@ public class ServerSession extends Session implements PrincipalHolder public MessageStore getMessageStore() { - return ((ServerConnection)getConnection()).getVirtualHost().getMessageStore(); + return getVirtualHost().getMessageStore(); } + public VirtualHost getVirtualHost() + { + return (VirtualHost) _connectionConfig.getVirtualHost(); + } + + public UUID getId() + { + return _id; + } + + public SessionConfigType getConfigType() + { + return SessionConfigType.getInstance(); + } + public ConfiguredObject getParent() + { + return getVirtualHost(); + } + + public boolean isDurable() + { + return false; + } + + public boolean isAttached() + { + return true; + } + + public long getDetachedLifespan() + { + return 0; + } + + public Long getExpiryTime() + { + return null; + } + + public Long getMaxClientRate() + { + return null; + } + + public ConnectionConfig getConnectionConfig() + { + return _connectionConfig; + } + + public String getSessionName() + { + return getName().toString(); + } } diff --git a/java/broker/src/main/java/org/apache/qpid/server/transport/ServerSessionDelegate.java b/java/broker/src/main/java/org/apache/qpid/server/transport/ServerSessionDelegate.java index 4ade799c59..3b0f990377 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/transport/ServerSessionDelegate.java +++ b/java/broker/src/main/java/org/apache/qpid/server/transport/ServerSessionDelegate.java @@ -28,6 +28,7 @@ import org.apache.qpid.server.exchange.*; import org.apache.qpid.server.queue.QueueRegistry; import org.apache.qpid.server.queue.AMQQueue; import org.apache.qpid.server.queue.AMQQueueFactory; +import org.apache.qpid.server.queue.BaseQueue; import org.apache.qpid.server.message.MessageTransferMessage; import org.apache.qpid.server.message.MessageMetaData_0_10; import org.apache.qpid.server.subscription.Subscription_0_10; @@ -42,6 +43,7 @@ import org.apache.qpid.framing.*; import java.util.ArrayList; import java.util.Collection; import java.util.Map; +import java.nio.ByteBuffer; public class ServerSessionDelegate extends SessionDelegate { @@ -218,11 +220,15 @@ public class ServerSessionDelegate extends SessionDelegate MessageMetaData_0_10 messageMetaData = new MessageMetaData_0_10(xfr); final MessageStore store = getVirtualHost(ssn).getMessageStore(); StoredMessage<MessageMetaData_0_10> storeMessage = store.addMessage(messageMetaData); - storeMessage.addContent(0,xfr.getBody()); + ByteBuffer body = xfr.getBody(); + if(body != null) + { + storeMessage.addContent(0, body); + } storeMessage.flushToStore(); MessageTransferMessage message = new MessageTransferMessage(storeMessage, ((ServerSession)ssn).getReference()); - ArrayList<AMQQueue> queues = exchange.route(message); + ArrayList<? extends BaseQueue> queues = exchange.route(message); @@ -355,7 +361,7 @@ public class ServerSessionDelegate extends SessionDelegate else { // TODO - check exchange has same properties - if(!exchange.getType().toString().equals(method.getType())) + if(!exchange.getTypeShortString().toString().equals(method.getType())) { exception(session, method, ExecutionErrorCode.NOT_ALLOWED, "Cannot redeclare with a different exchange type"); } @@ -419,7 +425,7 @@ public class ServerSessionDelegate extends SessionDelegate } else { - if(!exchange.getType().toString().equals(method.getType())) + if(!exchange.getTypeShortString().toString().equals(method.getType())) { exception(session, method, ExecutionErrorCode.NOT_ALLOWED, "Cannot redeclare with a different exchange type"); } @@ -525,7 +531,7 @@ public class ServerSessionDelegate extends SessionDelegate if(exchange != null) { result.setDurable(exchange.isDurable()); - result.setType(exchange.getType().toString()); + result.setType(exchange.getTypeShortString().toString()); result.setNotFound(false); } else @@ -582,30 +588,23 @@ public class ServerSessionDelegate extends SessionDelegate + "' to Queue: '" + method.getQueue() + "' not allowed"); } - else if(exchange.getType().equals(HeadersExchange.TYPE.getName()) && (!method.hasArguments() || method.getArguments() == null || !method.getArguments().containsKey("x-match"))) + else if(exchange.getTypeShortString().equals(HeadersExchange.TYPE.getName()) && (!method.hasArguments() || method.getArguments() == null || !method.getArguments().containsKey("x-match"))) { exception(session, method, ExecutionErrorCode.INTERNAL_ERROR, "Bindings to an exchange of type " + HeadersExchange.TYPE.getName() + " require an x-match header"); } else { - try - { - AMQShortString routingKey = new AMQShortString(method.getBindingKey()); - FieldTable fieldTable = FieldTable.convertToFieldTable(method.getArguments()); + AMQShortString routingKey = new AMQShortString(method.getBindingKey()); + FieldTable fieldTable = FieldTable.convertToFieldTable(method.getArguments()); - if (!exchange.isBound(routingKey, fieldTable, queue)) - { - queue.bind(exchange, routingKey, fieldTable); + if (!exchange.isBound(routingKey, fieldTable, queue)) + { + virtualHost.getBindingFactory().addBinding(method.getBindingKey(), queue, exchange, method.getArguments()); - } - else - { - // todo - } } - catch (AMQException e) + else { - e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. + // todo } } @@ -649,14 +648,7 @@ public class ServerSessionDelegate extends SessionDelegate } else { - try - { - queue.unBind(exchange, new AMQShortString(method.getBindingKey()), null); - } - catch (AMQException e) - { - throw new RuntimeException(e); - } + virtualHost.getBindingFactory().removeBinding(method.getBindingKey(), queue, exchange, null); } } @@ -827,7 +819,7 @@ public class ServerSessionDelegate extends SessionDelegate { queue.setDeleteOnNoConsumers(true); } - + final String alternateExchangeName = method.getAlternateExchange(); if(alternateExchangeName != null && alternateExchangeName.length() != 0) { @@ -870,11 +862,12 @@ public class ServerSessionDelegate extends SessionDelegate if (autoRegister) { + ExchangeRegistry exchangeRegistry = getExchangeRegistry(session); Exchange defaultExchange = exchangeRegistry.getDefaultExchange(); - queue.bind(defaultExchange, new AMQShortString(queueName), null); + virtualHost.getBindingFactory().addBinding(queueName, queue, defaultExchange, null); } @@ -1114,7 +1107,7 @@ public class ServerSessionDelegate extends SessionDelegate if(queue != null) { - result.setQueue(queue.getName().toString()); + result.setQueue(queue.getNameShortString().toString()); result.setDurable(queue.isDurable()); result.setExclusive(queue.isExclusive()); result.setAutoDelete(queue.isAutoDelete()); diff --git a/java/broker/src/main/java/org/apache/qpid/server/txn/AutoCommitTransaction.java b/java/broker/src/main/java/org/apache/qpid/server/txn/AutoCommitTransaction.java index 7b29106ba6..f674741057 100755 --- a/java/broker/src/main/java/org/apache/qpid/server/txn/AutoCommitTransaction.java +++ b/java/broker/src/main/java/org/apache/qpid/server/txn/AutoCommitTransaction.java @@ -22,6 +22,7 @@ package org.apache.qpid.server.txn; import org.apache.qpid.server.queue.AMQQueue; import org.apache.qpid.server.queue.QueueEntry; +import org.apache.qpid.server.queue.BaseQueue; import org.apache.qpid.server.message.EnqueableMessage; import org.apache.qpid.server.message.ServerMessage; import org.apache.qpid.server.store.TransactionLog; @@ -46,7 +47,7 @@ public class AutoCommitTransaction implements ServerTransaction postCommitAction.postCommit(); } - public void dequeue(AMQQueue queue, EnqueableMessage message, Action postCommitAction) + public void dequeue(BaseQueue queue, EnqueableMessage message, Action postCommitAction) { try @@ -105,7 +106,7 @@ public class AutoCommitTransaction implements ServerTransaction } - public void enqueue(AMQQueue queue, EnqueableMessage message, Action postCommitAction) + public void enqueue(BaseQueue queue, EnqueableMessage message, Action postCommitAction) { try { @@ -128,7 +129,7 @@ public class AutoCommitTransaction implements ServerTransaction } - public void enqueue(List<AMQQueue> queues, EnqueableMessage message, Action postCommitAction) + public void enqueue(List<? extends BaseQueue> queues, EnqueableMessage message, Action postCommitAction) { try { @@ -137,7 +138,7 @@ public class AutoCommitTransaction implements ServerTransaction { TransactionLog.Transaction txn = _transactionLog.newTransaction(); Long id = message.getMessageNumber(); - for(AMQQueue q : queues) + for(BaseQueue q : queues) { if(q.isDurable()) { diff --git a/java/broker/src/main/java/org/apache/qpid/server/txn/LocalTransaction.java b/java/broker/src/main/java/org/apache/qpid/server/txn/LocalTransaction.java index 9997fbe767..1124b0e812 100755 --- a/java/broker/src/main/java/org/apache/qpid/server/txn/LocalTransaction.java +++ b/java/broker/src/main/java/org/apache/qpid/server/txn/LocalTransaction.java @@ -2,6 +2,7 @@ package org.apache.qpid.server.txn; import org.apache.qpid.server.queue.AMQQueue; import org.apache.qpid.server.queue.QueueEntry; +import org.apache.qpid.server.queue.BaseQueue; import org.apache.qpid.server.message.EnqueableMessage; import org.apache.qpid.server.message.ServerMessage; import org.apache.qpid.server.store.TransactionLog; @@ -28,7 +29,7 @@ public class LocalTransaction implements ServerTransaction _postCommitActions.add(postCommitAction); } - public void dequeue(AMQQueue queue, EnqueableMessage message, Action postCommitAction) + public void dequeue(BaseQueue queue, EnqueableMessage message, Action postCommitAction) { if(message.isPersistent() && queue.isDurable()) { @@ -113,7 +114,7 @@ public class LocalTransaction implements ServerTransaction } } - public void enqueue(AMQQueue queue, EnqueableMessage message, Action postCommitAction) + public void enqueue(BaseQueue queue, EnqueableMessage message, Action postCommitAction) { if(message.isPersistent() && queue.isDurable()) { @@ -132,7 +133,7 @@ public class LocalTransaction implements ServerTransaction } - public void enqueue(List<AMQQueue> queues, EnqueableMessage message, Action postCommitAction) + public void enqueue(List<? extends BaseQueue> queues, EnqueableMessage message, Action postCommitAction) { @@ -140,7 +141,7 @@ public class LocalTransaction implements ServerTransaction { if(_transaction == null) { - for(AMQQueue queue : queues) + for(BaseQueue queue : queues) { if(queue.isDurable()) { @@ -155,7 +156,7 @@ public class LocalTransaction implements ServerTransaction try { - for(AMQQueue queue : queues) + for(BaseQueue queue : queues) { if(queue.isDurable()) { diff --git a/java/broker/src/main/java/org/apache/qpid/server/txn/ServerTransaction.java b/java/broker/src/main/java/org/apache/qpid/server/txn/ServerTransaction.java index 88bdc363c4..f3ef6569f3 100755 --- a/java/broker/src/main/java/org/apache/qpid/server/txn/ServerTransaction.java +++ b/java/broker/src/main/java/org/apache/qpid/server/txn/ServerTransaction.java @@ -20,15 +20,12 @@ */ package org.apache.qpid.server.txn; -import org.apache.qpid.server.queue.AMQQueue; -import org.apache.qpid.server.queue.QueueEntry; -import org.apache.qpid.server.message.ServerMessage; import org.apache.qpid.server.message.EnqueableMessage; -import org.apache.qpid.server.AMQChannel; +import org.apache.qpid.server.queue.BaseQueue; +import org.apache.qpid.server.queue.QueueEntry; -import java.util.List; -import java.util.SortedSet; import java.util.Collection; +import java.util.List; public interface ServerTransaction { @@ -45,13 +42,13 @@ public interface ServerTransaction public void onRollback(); } - void dequeue(AMQQueue queue, EnqueableMessage message, Action postCommitAction); + void dequeue(BaseQueue queue, EnqueableMessage message, Action postCommitAction); void dequeue(Collection<QueueEntry> ackedMessages, Action postCommitAction); - void enqueue(AMQQueue queue, EnqueableMessage message, Action postCommitAction); + void enqueue(BaseQueue queue, EnqueableMessage message, Action postCommitAction); - void enqueue(List<AMQQueue> queues, EnqueableMessage message, Action postCommitAction); + void enqueue(List<? extends BaseQueue> queues, EnqueableMessage message, Action postCommitAction); void commit(); diff --git a/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHost.java b/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHost.java index e4a382d275..c140e4a144 100755 --- a/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHost.java +++ b/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHost.java @@ -21,7 +21,10 @@ package org.apache.qpid.server.virtualhost; import org.apache.qpid.server.connection.IConnectionRegistry; +import org.apache.qpid.server.federation.BrokerLink; import org.apache.qpid.server.configuration.VirtualHostConfiguration; +import org.apache.qpid.server.configuration.VirtualHostConfig; +import org.apache.qpid.server.configuration.ConfigStore; import org.apache.qpid.server.queue.QueueRegistry; import org.apache.qpid.server.exchange.ExchangeRegistry; import org.apache.qpid.server.exchange.ExchangeFactory; @@ -31,8 +34,13 @@ import org.apache.qpid.server.store.DurableConfigurationStore; import org.apache.qpid.server.security.auth.manager.AuthenticationManager; import org.apache.qpid.server.security.access.ACLManager; import org.apache.qpid.server.management.ManagedObject; +import org.apache.qpid.server.registry.IApplicationRegistry; +import org.apache.qpid.server.binding.BindingFactory; -public interface VirtualHost +import java.util.UUID; +import java.util.TimerTask; + +public interface VirtualHost extends DurableConfigurationStore.Source, VirtualHostConfig { IConnectionRegistry getConnectionRegistry(); @@ -59,4 +67,24 @@ public interface VirtualHost void close() throws Exception; ManagedObject getManagedObject(); + + UUID getBrokerId(); + + void scheduleTask(long period, TimerTask task); + + + IApplicationRegistry getApplicationRegistry(); + + BindingFactory getBindingFactory(); + + void createBrokerConnection(String transport, + String host, + int port, + String vhost, + boolean durable, + String authMechanism, String username, String password); + + ConfigStore getConfigStore(); + + void removeBrokerConnection(BrokerLink brokerLink); } diff --git a/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostConfigRecoveryHandler.java b/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostConfigRecoveryHandler.java index c543531210..221ec0b639 100755 --- a/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostConfigRecoveryHandler.java +++ b/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostConfigRecoveryHandler.java @@ -34,10 +34,10 @@ import org.apache.qpid.server.exchange.Exchange; import org.apache.qpid.server.logging.subjects.MessageStoreLogSubject; import org.apache.qpid.server.logging.actors.CurrentActor; import org.apache.qpid.server.logging.messages.TransactionLogMessages; -import org.apache.qpid.server.logging.messages.MessageStoreMessages; import org.apache.qpid.server.message.AMQMessage; import org.apache.qpid.server.message.ServerMessage; import org.apache.qpid.server.message.MessageTransferMessage; +import org.apache.qpid.server.binding.BindingFactory; import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.framing.FieldTable; import org.apache.qpid.AMQException; @@ -215,7 +215,7 @@ public class VirtualHostConfigRecoveryHandler implements ConfigurationRecoveryHa if (queue == null) { _logger.error("Unkown queue: " + queueName + " cannot be bound to exchange: " - + exchange.getName()); + + exchange.getNameShortString()); } else { @@ -227,10 +227,18 @@ public class VirtualHostConfigRecoveryHandler implements ConfigurationRecoveryHa argumentsFT = new FieldTable(org.apache.mina.common.ByteBuffer.wrap(buf),buf.limit()); } - _logger.info("Restoring binding: (Exchange: " + exchange.getName() + ", Queue: " + queueName - + ", Routing Key: " + bindingKey + ", Arguments: " + argumentsFT + ")"); + BindingFactory bf = _virtualHost.getBindingFactory(); - queue.bind(exchange, bindingKey == null ? null : new AMQShortString(bindingKey), argumentsFT); + Map<String, Object> argumentMap = FieldTable.convertToMap(argumentsFT); + + if(bf.getBinding(bindingKey, queue, exchange, argumentMap) == null) + { + + _logger.info("Restoring binding: (Exchange: " + exchange.getNameShortString() + ", Queue: " + queueName + + ", Routing Key: " + bindingKey + ", Arguments: " + argumentsFT + ")"); + + bf.restoreBinding(bindingKey, queue, exchange, argumentMap); + } } } @@ -271,7 +279,7 @@ public class VirtualHostConfigRecoveryHandler implements ConfigurationRecoveryHa if (_logger.isDebugEnabled()) { - _logger.debug("On recovery, delivering " + message.getMessageNumber() + " to " + queue.getName()); + _logger.debug("On recovery, delivering " + message.getMessageNumber() + " to " + queue.getNameShortString()); } Integer count = _queueRecoveries.get(queueName); @@ -286,7 +294,7 @@ public class VirtualHostConfigRecoveryHandler implements ConfigurationRecoveryHa } else { - _logger.warn("Message id " + messageId + " referenced in log as enqueue in queue " + queue.getName() + " is unknwon, entry will be discarded"); + _logger.warn("Message id " + messageId + " referenced in log as enqueue in queue " + queue.getNameShortString() + " is unknwon, entry will be discarded"); TransactionLog.Transaction txn = _transactionLog.newTransaction(); txn.dequeueMessage(queue, messageId); txn.commitTranAsync(); @@ -333,7 +341,7 @@ public class VirtualHostConfigRecoveryHandler implements ConfigurationRecoveryHa CurrentActor.get().message(_logSubject, TransactionLogMessages.TXN_1005(entry.getValue(), entry.getKey())); CurrentActor.get().message(_logSubject, TransactionLogMessages.TXN_1006(entry.getKey(), true)); - } + } CurrentActor.get().message(_logSubject, TransactionLogMessages.TXN_1006(null, false)); } diff --git a/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostImpl.java b/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostImpl.java index 2f1528eb43..b208872a5a 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostImpl.java +++ b/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostImpl.java @@ -20,19 +20,21 @@ */ package org.apache.qpid.server.virtualhost; -import org.apache.commons.configuration.ConfigurationException; import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration.ConfigurationException; import org.apache.log4j.Logger; + import org.apache.qpid.AMQException; import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.framing.FieldTable; import org.apache.qpid.server.AMQBrokerManagerMBean; -import org.apache.qpid.server.logging.actors.CurrentActor; -import org.apache.qpid.server.logging.messages.VirtualHostMessages; -import org.apache.qpid.server.logging.subjects.MessageStoreLogSubject; -import org.apache.qpid.server.logging.LogSubject; +import org.apache.qpid.server.binding.BindingFactory; +import org.apache.qpid.server.configuration.BrokerConfig; +import org.apache.qpid.server.configuration.ConfigStore; +import org.apache.qpid.server.configuration.ConfiguredObject; import org.apache.qpid.server.configuration.ExchangeConfiguration; import org.apache.qpid.server.configuration.QueueConfiguration; +import org.apache.qpid.server.configuration.VirtualHostConfigType; import org.apache.qpid.server.configuration.VirtualHostConfiguration; import org.apache.qpid.server.connection.ConnectionRegistry; import org.apache.qpid.server.connection.IConnectionRegistry; @@ -41,6 +43,11 @@ import org.apache.qpid.server.exchange.DefaultExchangeRegistry; import org.apache.qpid.server.exchange.Exchange; import org.apache.qpid.server.exchange.ExchangeFactory; import org.apache.qpid.server.exchange.ExchangeRegistry; +import org.apache.qpid.server.federation.BrokerLink; +import org.apache.qpid.server.logging.LogSubject; +import org.apache.qpid.server.logging.actors.CurrentActor; +import org.apache.qpid.server.logging.messages.VirtualHostMessages; +import org.apache.qpid.server.logging.subjects.MessageStoreLogSubject; import org.apache.qpid.server.management.AMQManagedObject; import org.apache.qpid.server.management.ManagedObject; import org.apache.qpid.server.queue.AMQQueue; @@ -48,14 +55,15 @@ import org.apache.qpid.server.queue.AMQQueueFactory; import org.apache.qpid.server.queue.DefaultQueueRegistry; import org.apache.qpid.server.queue.QueueRegistry; import org.apache.qpid.server.registry.ApplicationRegistry; +import org.apache.qpid.server.registry.IApplicationRegistry; import org.apache.qpid.server.security.access.ACLManager; import org.apache.qpid.server.security.access.Accessable; import org.apache.qpid.server.security.auth.manager.AuthenticationManager; import org.apache.qpid.server.security.auth.manager.PrincipalDatabaseAuthenticationManager; -import org.apache.qpid.server.store.MessageStore; +import org.apache.qpid.server.store.ConfigurationRecoveryHandler; import org.apache.qpid.server.store.DurableConfigurationStore; +import org.apache.qpid.server.store.MessageStore; import org.apache.qpid.server.store.TransactionLog; -import org.apache.qpid.server.store.ConfigurationRecoveryHandler; import javax.management.NotCompliantMBeanException; import java.util.Collections; @@ -63,6 +71,9 @@ import java.util.LinkedList; import java.util.List; import java.util.Timer; import java.util.TimerTask; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; + public class VirtualHostImpl implements Accessable, VirtualHost { @@ -88,9 +99,17 @@ public class VirtualHostImpl implements Accessable, VirtualHost private ACLManager _accessManager; - private final Timer _houseKeepingTimer; + private final Timer _timer; + private final IApplicationRegistry _appRegistry; private VirtualHostConfiguration _configuration; private DurableConfigurationStore _durableConfigurationStore; + private BindingFactory _bindingFactory; + private BrokerConfig _broker; + private UUID _id; + + + private final long _createTime = System.currentTimeMillis(); + private final ConcurrentHashMap<BrokerLink,BrokerLink> _links = new ConcurrentHashMap<BrokerLink, BrokerLink>(); public void setAccessableName(String name) { @@ -113,6 +132,26 @@ public class VirtualHostImpl implements Accessable, VirtualHost return _configuration; } + public UUID getId() + { + return _id; //To change body of implemented methods use File | Settings | File Templates. + } + + public VirtualHostConfigType getConfigType() + { + return VirtualHostConfigType.getInstance(); + } + + public ConfiguredObject getParent() + { + return getBroker(); + } + + public boolean isDurable() + { + return false; + } + /** * Abstract MBean class. This has some of the methods implemented from management intrerface for exchanges. Any * implementaion of an Exchange MBean should extend this class. @@ -141,23 +180,28 @@ public class VirtualHostImpl implements Accessable, VirtualHost } // End of MBean class - /** - * Normal Constructor - * - * @param hostConfig - * - * @throws Exception - */ - public VirtualHostImpl(VirtualHostConfiguration hostConfig) throws Exception + + + public VirtualHostImpl(IApplicationRegistry appRegistry, VirtualHostConfiguration hostConfig) throws Exception { - this(hostConfig, null); + this(appRegistry, hostConfig, null); } + public VirtualHostImpl(VirtualHostConfiguration hostConfig, MessageStore store) throws Exception { + this(ApplicationRegistry.getInstance(),hostConfig,store); + } + + private VirtualHostImpl(IApplicationRegistry appRegistry, VirtualHostConfiguration hostConfig, MessageStore store) throws Exception + { + _appRegistry = appRegistry; + _broker = appRegistry.getBroker(); _configuration = hostConfig; _name = hostConfig.getName(); + _id = appRegistry.getConfigStore().createId(); + CurrentActor.get().message(VirtualHostMessages.VHT_CREATED(_name)); if (_name == null || _name.length() == 0) @@ -169,7 +213,7 @@ public class VirtualHostImpl implements Accessable, VirtualHost _connectionRegistry = new ConnectionRegistry(this); - _houseKeepingTimer = new Timer("Queue-housekeeping-" + _name, true); + _timer = new Timer("TimerThread-" + _name + ":", true); _queueRegistry = new DefaultQueueRegistry(this); @@ -178,6 +222,7 @@ public class VirtualHostImpl implements Accessable, VirtualHost _exchangeRegistry = new DefaultExchangeRegistry(this); + //Create a temporary RT to store the durable entries from the config file // so we can replay them in to the real _RT after it has been loaded. /// This should be removed after the _RT has been fully split from the the TL @@ -189,6 +234,8 @@ public class VirtualHostImpl implements Accessable, VirtualHost // This needs to be after the RT has been defined as it creates the default durable exchanges. _exchangeRegistry.initialise(); + _bindingFactory = new BindingFactory(this); + initialiseModel(hostConfig); if (store != null) @@ -205,9 +252,11 @@ public class VirtualHostImpl implements Accessable, VirtualHost initialiseMessageStore(hostConfig); } + + //Now that the RT has been initialised loop through the persistent queues/exchanges created from the config // file and write them in to the new routing Table. - for (StartupRoutingTable.CreateQueueTuple cqt : configFileRT.queue) +/* for (StartupRoutingTable.CreateQueueTuple cqt : configFileRT.queue) { getDurableConfigurationStore().createQueue(cqt.queue, cqt.arguments); } @@ -220,7 +269,7 @@ public class VirtualHostImpl implements Accessable, VirtualHost for (StartupRoutingTable.CreateBindingTuple cbt : configFileRT.bindings) { getDurableConfigurationStore().bindQueue(cbt.exchange, cbt.routingKey, cbt.queue, cbt.arguments); - } + }*/ _authenticationManager = new PrincipalDatabaseAuthenticationManager(_name, hostConfig); @@ -250,7 +299,7 @@ public class VirtualHostImpl implements Accessable, VirtualHost } catch (Exception e) { - _logger.error("Exception in housekeeping for queue: " + q.getName().toString(), e); + _logger.error("Exception in housekeeping for queue: " + q.getNameShortString().toString(), e); //Don't throw exceptions as this will stop the // house keeping task from running. } @@ -258,9 +307,8 @@ public class VirtualHostImpl implements Accessable, VirtualHost } } - _houseKeepingTimer.scheduleAtFixedRate(new RemoveExpiredMessagesTask(), - period / 2, - period); + final TimerTask expiredMessagesTask = new RemoveExpiredMessagesTask(); + scheduleTask(period, expiredMessagesTask); class ForceChannelClosuresTask extends TimerTask { @@ -272,6 +320,12 @@ public class VirtualHostImpl implements Accessable, VirtualHost } } + public void scheduleTask(final long period, final TimerTask task) + { + _timer.scheduleAtFixedRate(task, period / 2, period); + } + + private void initialiseMessageStore(VirtualHostConfiguration hostConfig) throws Exception { String messageStoreClass = hostConfig.getMessageStoreClass(); @@ -377,7 +431,7 @@ public class VirtualHostImpl implements Accessable, VirtualHost List routingKeys = queueConfiguration.getRoutingKeys(); if (routingKeys == null || routingKeys.isEmpty()) { - routingKeys = Collections.singletonList(queue.getName()); + routingKeys = Collections.singletonList(queue.getNameShortString()); } for (Object routingKeyNameObj : routingKeys) @@ -387,12 +441,12 @@ public class VirtualHostImpl implements Accessable, VirtualHost { _logger.info("Binding queue:" + queue + " with routing key '" + routingKey + "' to exchange:" + this); } - queue.bind(exchange, routingKey, null); + _bindingFactory.addBinding(routingKey.toString(), queue, exchange, null); } if (exchange != _exchangeRegistry.getDefaultExchange()) { - queue.bind(_exchangeRegistry.getDefaultExchange(), queue.getName(), null); + _bindingFactory.addBinding(queue.getNameShortString().toString(), queue, exchange, null); } } @@ -401,6 +455,26 @@ public class VirtualHostImpl implements Accessable, VirtualHost return _name; } + public BrokerConfig getBroker() + { + return _broker; + } + + public String getFederationTag() + { + return _broker.getFederationTag(); + } + + public void setBroker(final BrokerConfig broker) + { + _broker = broker; + } + + public long getCreateTime() + { + return _createTime; + } + public QueueRegistry getQueueRegistry() { return _queueRegistry; @@ -457,9 +531,9 @@ public class VirtualHostImpl implements Accessable, VirtualHost } //Stop Housekeeping - if (_houseKeepingTimer != null) + if (_timer != null) { - _houseKeepingTimer.cancel(); + _timer.cancel(); } //Close MessageStore @@ -481,6 +555,59 @@ public class VirtualHostImpl implements Accessable, VirtualHost return _virtualHostMBean; } + public UUID getBrokerId() + { + return _appRegistry.getBrokerId(); + } + + public IApplicationRegistry getApplicationRegistry() + { + return _appRegistry; + } + + public BindingFactory getBindingFactory() + { + return _bindingFactory; + } + + public void createBrokerConnection(final String transport, + final String host, + final int port, + final String vhost, + final boolean durable, + final String authMechanism, + final String username, + final String password) + { + BrokerLink blink = new BrokerLink(this, transport, host, port, vhost, durable, authMechanism, username, password); + _links.putIfAbsent(blink,blink); + getConfigStore().addConfiguredObject(blink); + } + + public void removeBrokerConnection(final String transport, + final String host, + final int port, + final String vhost) + { + removeBrokerConnection(new BrokerLink(this, transport, host, port, vhost, false, null,null,null)); + + } + + public void removeBrokerConnection(BrokerLink blink) + { + blink = _links.get(blink); + if(blink != null) + { + blink.close(); + getConfigStore().removeConfiguredObject(blink); + } + } + + public ConfigStore getConfigStore() + { + return getApplicationRegistry().getConfigStore(); + } + /** * Temporary Startup RT class to record the creation of persistent queues / exchanges. * diff --git a/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostRegistry.java b/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostRegistry.java index b86e0d0baf..5975eeec3d 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostRegistry.java +++ b/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostRegistry.java @@ -21,6 +21,7 @@ package org.apache.qpid.server.virtualhost;
import org.apache.qpid.server.registry.ApplicationRegistry;
+import org.apache.qpid.server.configuration.ConfigStore;
import java.util.ArrayList;
import java.util.Collection;
@@ -52,7 +53,7 @@ public class VirtualHostRegistry public VirtualHost getVirtualHost(String name)
{
- if(name == null || name.trim().length() == 0 )
+ if(name == null || name.trim().length() == 0 || "/".equals(name.trim()))
{
name = getDefaultVirtualHostName();
}
@@ -60,6 +61,11 @@ public class VirtualHostRegistry return _registry.get(name);
}
+ public VirtualHost getDefaultVirtualHost()
+ {
+ return getVirtualHost(getDefaultVirtualHostName());
+ }
+
private String getDefaultVirtualHostName()
{
return _defaultVirtualHostName;
@@ -80,4 +86,9 @@ public class VirtualHostRegistry {
return _applicationRegistry;
}
+
+ public ConfigStore getConfigStore()
+ {
+ return _applicationRegistry.getConfigStore();
+ }
}
diff --git a/java/broker/src/main/java/org/apache/qpid/tools/messagestore/MessageStoreTool.java b/java/broker/src/main/java/org/apache/qpid/tools/messagestore/MessageStoreTool.java index faa7b85d58..f26611f0bc 100644 --- a/java/broker/src/main/java/org/apache/qpid/tools/messagestore/MessageStoreTool.java +++ b/java/broker/src/main/java/org/apache/qpid/tools/messagestore/MessageStoreTool.java @@ -219,7 +219,7 @@ public class MessageStoreTool _console.println(""); - _console.println(BOILER_PLATE); + _console.println(BOILER_PLATE); runCLI(); } @@ -495,13 +495,13 @@ public class MessageStoreTool if (_exchange != null) { status.append("["); - status.append(_exchange.getName()); + status.append(_exchange.getNameShortString()); status.append("]"); if (_queue != null) { status.append("->'"); - status.append(_queue.getName()); + status.append(_queue.getNameShortString()); status.append("'"); if (_msgids != null) diff --git a/java/broker/src/main/java/org/apache/qpid/tools/messagestore/commands/Copy.java b/java/broker/src/main/java/org/apache/qpid/tools/messagestore/commands/Copy.java index ef3599bdc8..348c95572d 100644 --- a/java/broker/src/main/java/org/apache/qpid/tools/messagestore/commands/Copy.java +++ b/java/broker/src/main/java/org/apache/qpid/tools/messagestore/commands/Copy.java @@ -52,7 +52,7 @@ public class Copy extends Move protected void doCommand(AMQQueue fromQueue, long start, long end, AMQQueue toQueue) { ServerTransaction txn = new LocalTransaction(fromQueue.getVirtualHost().getTransactionLog()); - fromQueue.copyMessagesToAnotherQueue(start, end, toQueue.getName().toString(), txn); + fromQueue.copyMessagesToAnotherQueue(start, end, toQueue.getNameShortString().toString(), txn); txn.commit(); } diff --git a/java/broker/src/main/java/org/apache/qpid/tools/messagestore/commands/List.java b/java/broker/src/main/java/org/apache/qpid/tools/messagestore/commands/List.java index ab8e781df5..3c4a0c8fac 100644 --- a/java/broker/src/main/java/org/apache/qpid/tools/messagestore/commands/List.java +++ b/java/broker/src/main/java/org/apache/qpid/tools/messagestore/commands/List.java @@ -292,12 +292,12 @@ public class List extends AbstractCommand { if (exchange.isBound(queue)) { - data.add(queue.getName().toString()); + data.add(queue.getNameShortString().toString()); } } else { - data.add(queue.getName().toString()); + data.add(queue.getNameShortString().toString()); } } diff --git a/java/broker/src/main/java/org/apache/qpid/tools/messagestore/commands/Move.java b/java/broker/src/main/java/org/apache/qpid/tools/messagestore/commands/Move.java index 6a5e2a6025..615f6ec1c2 100644 --- a/java/broker/src/main/java/org/apache/qpid/tools/messagestore/commands/Move.java +++ b/java/broker/src/main/java/org/apache/qpid/tools/messagestore/commands/Move.java @@ -196,7 +196,7 @@ public class Move extends AbstractCommand protected void doCommand(AMQQueue fromQueue, long start, long id, AMQQueue toQueue) { ServerTransaction txn = new LocalTransaction(fromQueue.getVirtualHost().getTransactionLog()); - fromQueue.moveMessagesToAnotherQueue(start, id, toQueue.getName().toString(), txn); + fromQueue.moveMessagesToAnotherQueue(start, id, toQueue.getNameShortString().toString(), txn); txn.commit(); } } |