001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.activemq.broker.region.virtual;
018
019import java.util.Collection;
020
021import org.apache.activemq.broker.Broker;
022import org.apache.activemq.broker.ConnectionContext;
023import org.apache.activemq.broker.region.Destination;
024import org.apache.activemq.command.ActiveMQDestination;
025import org.apache.activemq.command.CommandTypes;
026
027public abstract class CompositeDestination implements VirtualDestination {
028
029    private String name;
030    private Collection forwardTo;
031    private boolean forwardOnly = true;
032    private boolean concurrentSend = false;
033
034    @Override
035    public Destination intercept(Destination destination) {
036        return new CompositeDestinationFilter(destination, getForwardTo(), isForwardOnly(), isConcurrentSend());
037    }
038
039    @Override
040    public void create(Broker broker, ConnectionContext context, ActiveMQDestination destination) {
041    }
042
043    @Override
044    public void remove(Destination destination) {
045    }
046
047    public String getName() {
048        return name;
049    }
050
051    /**
052     * Sets the name of this composite destination
053     */
054    public void setName(String name) {
055        this.name = name;
056    }
057
058    public Collection getForwardTo() {
059        return forwardTo;
060    }
061
062    /**
063     * Sets the list of destinations to forward to
064     */
065    public void setForwardTo(Collection forwardDestinations) {
066        this.forwardTo = forwardDestinations;
067    }
068
069    public boolean isForwardOnly() {
070        return forwardOnly;
071    }
072
073    /**
074     * Sets if the virtual destination is forward only (and so there is no
075     * physical queue to match the virtual queue) or if there is also a physical
076     * queue with the same name).
077     */
078    public void setForwardOnly(boolean forwardOnly) {
079        this.forwardOnly = forwardOnly;
080    }
081
082    @Deprecated
083    public boolean isCopyMessage() {
084        return true;
085    }
086
087    /**
088     * Sets whether a copy of the message will be sent to each destination.
089     * Defaults to true so that the forward destination is set as the
090     * destination of the message
091     *
092     * @deprecated this option will be removed in a later release, message are always copied.
093     */
094    @Deprecated
095    public void setCopyMessage(boolean copyMessage) {
096    }
097
098    /**
099     * when true, sends are done in parallel with the broker executor
100     */
101    public void setConcurrentSend(boolean concurrentSend) {
102        this.concurrentSend = concurrentSend;
103    }
104
105    public boolean isConcurrentSend() {
106        return this.concurrentSend;
107    }
108
109    @Override
110    public ActiveMQDestination getMappedDestinations() {
111        final ActiveMQDestination[] destinations = new ActiveMQDestination[forwardTo.size()];
112        int i = 0;
113        for (Object dest : forwardTo) {
114            if (dest instanceof FilteredDestination) {
115                FilteredDestination filteredDestination = (FilteredDestination) dest;
116                destinations[i++] = filteredDestination.getDestination();
117            } else if (dest instanceof ActiveMQDestination) {
118                destinations[i++] = (ActiveMQDestination) dest;
119            } else {
120                // highly unlikely, but just in case!
121                throw new IllegalArgumentException("Unknown mapped destination type " + dest);
122            }
123        }
124
125        // used just for matching destination paths
126        return new ActiveMQDestination(destinations) {
127            @Override
128            protected String getQualifiedPrefix() {
129                return "mapped://";
130            }
131
132            @Override
133            public byte getDestinationType() {
134                return QUEUE_TYPE | TOPIC_TYPE;
135            }
136
137            @Override
138            public byte getDataStructureType() {
139                return CommandTypes.ACTIVEMQ_QUEUE | CommandTypes.ACTIVEMQ_TOPIC;
140            }
141        };
142    }
143
144    @Override
145    public int hashCode() {
146        final int prime = 31;
147        int result = 1;
148        result = prime * result + (concurrentSend ? 1231 : 1237);
149        result = prime * result + (forwardOnly ? 1231 : 1237);
150        result = prime * result + ((forwardTo == null) ? 0 : forwardTo.hashCode());
151        result = prime * result + ((name == null) ? 0 : name.hashCode());
152        return result;
153    }
154
155    @Override
156    public boolean equals(Object obj) {
157        if (this == obj) {
158            return true;
159        }
160
161        if (obj == null) {
162            return false;
163        }
164
165        if (getClass() != obj.getClass()) {
166            return false;
167        }
168
169        CompositeDestination other = (CompositeDestination) obj;
170        if (concurrentSend != other.concurrentSend) {
171            return false;
172        }
173
174        if (forwardOnly != other.forwardOnly) {
175            return false;
176        }
177
178        if (forwardTo == null) {
179            if (other.forwardTo != null) {
180                return false;
181            }
182        } else if (!forwardTo.equals(other.forwardTo)) {
183            return false;
184        }
185
186        if (name == null) {
187            if (other.name != null)
188                return false;
189        } else if (!name.equals(other.name)) {
190            return false;
191        }
192
193        return true;
194    }
195}