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