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    private boolean sendWhenNotMatched = false;
034
035    @Override
036    public Destination intercept(Destination destination) {
037        return new CompositeDestinationFilter(destination, getForwardTo(), isForwardOnly(),isSendWhenNotMatched(), isConcurrentSend());
038    }
039
040    @Override
041    public void create(Broker broker, ConnectionContext context, ActiveMQDestination destination) {
042    }
043
044    @Override
045    public void remove(Destination destination) {
046    }
047
048    public String getName() {
049        return name;
050    }
051
052    /**
053     * Sets the name of this composite destination
054     */
055    public void setName(String name) {
056        this.name = name;
057    }
058
059    public Collection getForwardTo() {
060        return forwardTo;
061    }
062
063    /**
064     * Sets the list of destinations to forward to
065     */
066    public void setForwardTo(Collection forwardDestinations) {
067        this.forwardTo = forwardDestinations;
068    }
069
070    public boolean isForwardOnly() {
071        return forwardOnly;
072    }
073
074    /**
075     * Sets if the virtual destination is forward only (and so there is no
076     * physical queue to match the virtual queue) or if there is also a physical
077     * queue with the same name).
078     */
079    public void setForwardOnly(boolean forwardOnly) {
080        this.forwardOnly = forwardOnly;
081    }
082
083    @Deprecated
084    public boolean isCopyMessage() {
085        return true;
086    }
087
088    /**
089     * Sets whether a copy of the message will be sent to each destination.
090     * Defaults to true so that the forward destination is set as the
091     * destination of the message
092     *
093     * @deprecated this option will be removed in a later release, message are always copied.
094     */
095    @Deprecated
096    public void setCopyMessage(boolean copyMessage) {
097    }
098
099    /**
100     * when true, sends are done in parallel with the broker executor
101     */
102    public void setConcurrentSend(boolean concurrentSend) {
103        this.concurrentSend = concurrentSend;
104    }
105
106    public boolean isConcurrentSend() {
107        return this.concurrentSend;
108    }
109
110    @Override
111    public ActiveMQDestination getMappedDestinations() {
112        final ActiveMQDestination[] destinations = new ActiveMQDestination[forwardTo.size()];
113        int i = 0;
114        for (Object dest : forwardTo) {
115            if (dest instanceof FilteredDestination) {
116                FilteredDestination filteredDestination = (FilteredDestination) dest;
117                destinations[i++] = filteredDestination.getDestination();
118            } else if (dest instanceof ActiveMQDestination) {
119                destinations[i++] = (ActiveMQDestination) dest;
120            } else {
121                // highly unlikely, but just in case!
122                throw new IllegalArgumentException("Unknown mapped destination type " + dest);
123            }
124        }
125
126        // used just for matching destination paths
127        return new ActiveMQDestination(destinations) {
128            @Override
129            protected String getQualifiedPrefix() {
130                return "mapped://";
131            }
132
133            @Override
134            public byte getDestinationType() {
135                return QUEUE_TYPE | TOPIC_TYPE;
136            }
137
138            @Override
139            public byte getDataStructureType() {
140                return CommandTypes.ACTIVEMQ_QUEUE | CommandTypes.ACTIVEMQ_TOPIC;
141            }
142        };
143    }
144
145    @Override
146    public int hashCode() {
147        final int prime = 31;
148        int result = 1;
149        result = prime * result + (concurrentSend ? 1231 : 1237);
150        result = prime * result + (forwardOnly ? 1231 : 1237);
151        result = prime * result + ((forwardTo == null) ? 0 : forwardTo.hashCode());
152        result = prime * result + ((name == null) ? 0 : name.hashCode());
153        return result;
154    }
155
156    @Override
157    public boolean equals(Object obj) {
158        if (this == obj) {
159            return true;
160        }
161
162        if (obj == null) {
163            return false;
164        }
165
166        if (getClass() != obj.getClass()) {
167            return false;
168        }
169
170        CompositeDestination other = (CompositeDestination) obj;
171        if (concurrentSend != other.concurrentSend) {
172            return false;
173        }
174
175        if (forwardOnly != other.forwardOnly) {
176            return false;
177        }
178
179        if (forwardTo == null) {
180            if (other.forwardTo != null) {
181                return false;
182            }
183        } else if (!forwardTo.equals(other.forwardTo)) {
184            return false;
185        }
186
187        if (name == null) {
188            if (other.name != null)
189                return false;
190        } else if (!name.equals(other.name)) {
191            return false;
192        }
193
194        return true;
195    }
196    
197    public boolean isSendWhenNotMatched() {
198                return sendWhenNotMatched;
199        }
200
201        public void setSendWhenNotMatched(boolean sendWhenNotMatched) {
202                this.sendWhenNotMatched = sendWhenNotMatched;
203        }
204}