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}