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.plugin; 018 019import java.util.regex.Pattern; 020 021import org.apache.activemq.broker.Broker; 022import org.apache.activemq.broker.BrokerFilter; 023import org.apache.activemq.broker.ConnectionContext; 024import org.apache.activemq.broker.region.MessageReference; 025import org.apache.activemq.broker.region.Subscription; 026import org.apache.activemq.command.ActiveMQDestination; 027import org.apache.activemq.command.Message; 028import org.slf4j.Logger; 029import org.slf4j.LoggerFactory; 030 031/** 032 */ 033public class DiscardingDLQBroker extends BrokerFilter { 034 public static Logger log = LoggerFactory.getLogger(DiscardingDLQBroker.class); 035 private boolean dropTemporaryTopics = true; 036 private boolean dropTemporaryQueues = true; 037 private boolean dropAll = true; 038 private Pattern[] destFilter; 039 private int reportInterval = 1000; 040 private long dropCount = 0; 041 042 public DiscardingDLQBroker(Broker next) { 043 super(next); 044 } 045 046 @Override 047 public boolean sendToDeadLetterQueue(ConnectionContext ctx, MessageReference msgRef, Subscription subscription, Throwable poisonCause) { 048 log.trace("Discarding DLQ BrokerFilter[pass through] - skipping message: {}", (msgRef != null ? msgRef.getMessage() : null)); 049 boolean dropped = true; 050 Message msg = null; 051 ActiveMQDestination dest = null; 052 String destName = null; 053 msg = msgRef.getMessage(); 054 dest = msg.getDestination(); 055 destName = dest.getPhysicalName(); 056 057 if (dest == null || destName == null) { 058 // do nothing, no need to forward it 059 skipMessage("NULL DESTINATION", msgRef); 060 } else if (dropAll) { 061 // do nothing 062 skipMessage("dropAll", msgRef); 063 } else if (dropTemporaryTopics && dest.isTemporary() && dest.isTopic()) { 064 // do nothing 065 skipMessage("dropTemporaryTopics", msgRef); 066 } else if (dropTemporaryQueues && dest.isTemporary() && dest.isQueue()) { 067 // do nothing 068 skipMessage("dropTemporaryQueues", msgRef); 069 } else if (destFilter != null && matches(destName)) { 070 // do nothing 071 skipMessage("dropOnly", msgRef); 072 } else { 073 dropped = false; 074 return next.sendToDeadLetterQueue(ctx, msgRef, subscription, poisonCause); 075 } 076 077 if (dropped && getReportInterval() > 0) { 078 if ((++dropCount) % getReportInterval() == 0) { 079 log.info("Total of {} messages were discarded, since their destination was the dead letter queue", dropCount); 080 } 081 } 082 083 return false; 084 } 085 086 public boolean matches(String destName) { 087 for (int i = 0; destFilter != null && i < destFilter.length; i++) { 088 if (destFilter[i] != null && destFilter[i].matcher(destName).matches()) { 089 return true; 090 } 091 } 092 return false; 093 } 094 095 private void skipMessage(String prefix, MessageReference msgRef) { 096 log.debug("Discarding DLQ BrokerFilter[{}] - skipping message: {}", prefix, (msgRef != null ? msgRef.getMessage() : null)); 097 } 098 099 public void setDropTemporaryTopics(boolean dropTemporaryTopics) { 100 this.dropTemporaryTopics = dropTemporaryTopics; 101 } 102 103 public void setDropTemporaryQueues(boolean dropTemporaryQueues) { 104 this.dropTemporaryQueues = dropTemporaryQueues; 105 } 106 107 public void setDropAll(boolean dropAll) { 108 this.dropAll = dropAll; 109 } 110 111 public void setDestFilter(Pattern[] destFilter) { 112 this.destFilter = destFilter; 113 } 114 115 public void setReportInterval(int reportInterval) { 116 this.reportInterval = reportInterval; 117 } 118 119 public boolean isDropTemporaryTopics() { 120 return dropTemporaryTopics; 121 } 122 123 public boolean isDropTemporaryQueues() { 124 return dropTemporaryQueues; 125 } 126 127 public boolean isDropAll() { 128 return dropAll; 129 } 130 131 public Pattern[] getDestFilter() { 132 return destFilter; 133 } 134 135 public int getReportInterval() { 136 return reportInterval; 137 } 138}