/*
* Copyright 2009 James Abley
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.eternus.ratelimit.jmx;
import javax.management.MBeanNotificationInfo;
import javax.management.Notification;
import javax.management.NotificationBroadcasterSupport;
import javax.management.monitor.MonitorNotification;
import com.eternus.ratelimit.Key;
import com.eternus.ratelimit.RateLimiter;
import com.eternus.ratelimit.Token;
/**
* JMX MBean which will send out notifications around a decorated {@link RateLimiter} implementation.
*
* @author jabley
*
*/
public class ManagedRateLimiter extends NotificationBroadcasterSupport implements ManagedRateLimiterMBean {
/**
* The name of the JXM notification that will be sent for successfully serviced requests.
*/
private static final String JMX_MONITOR_RATE_LIMIT_SERVICE_TYPE = "jmx.monitor.rate-limit.service";
/**
* The non-null delegate.
*/
private final RateLimiter delegate;
/**
* The JMX notification sequence number.
*/
private long sequenceNumber;
/**
* Creates a new {@link ManagedRateLimiter} which will delegate the implementation to the specified non-null
* {@link RateLimiter}.
*
* @param delegate
* a non-null {@link RateLimiter} around which this MBean will send notifications
*/
public ManagedRateLimiter(RateLimiter delegate) {
if (delegate == null) {
throw new IllegalArgumentException("delegate cannot be null");
}
this.delegate = delegate;
}
/**
* {@inheritDoc}
*/
@Override
public MBeanNotificationInfo[] getNotificationInfo() {
String[] types = new String[] { JMX_MONITOR_RATE_LIMIT_SERVICE_TYPE,
MonitorNotification.THRESHOLD_VALUE_EXCEEDED };
MBeanNotificationInfo info = new MBeanNotificationInfo(types, Notification.class.getName(),
"rate-limited request processed");
return new MBeanNotificationInfo[] { info };
}
/**
* {@inheritDoc}
*/
public Token getToken(Key key) {
Token token = delegate.getToken(key);
if (token.isUsable()) {
sendNotification(new Notification(JMX_MONITOR_RATE_LIMIT_SERVICE_TYPE, this, getSequenceNumber(),
"allowed request " + key));
} else {
sendNotification(new Notification(MonitorNotification.THRESHOLD_VALUE_EXCEEDED, this, getSequenceNumber(),
"denied request " + key));
}
return token;
}
/**
* {@inheritDoc}
*/
public boolean isEnabled() {
return this.delegate.isEnabled();
}
/**
* {@inheritDoc}
*/
public void setEnabled(boolean enabled) {
this.delegate.setEnabled(enabled);
}
/**
* {@inheritDoc}
*/
public int getAllowedRequests() {
return delegate.getAllowedRequests();
}
/**
* {@inheritDoc}
*/
public int getDuration() {
return delegate.getDuration();
}
/**
* {@inheritDoc}
*/
public void setAllowedRequests(int allowedRequests) {
delegate.setAllowedRequests(allowedRequests);
}
/**
* {@inheritDoc}
*/
public void setDuration(int durationInSeconds) {
delegate.setDuration(durationInSeconds);
}
/**
* Returns the next sequence number for the JMX notification.
*
* @return the next positive sequence number
*/
private synchronized long getSequenceNumber() {
return ++this.sequenceNumber;
}
}