org.echocat.jemoni.jmx.support.CacheDynamicMBean.java Source code

Java tutorial

Introduction

Here is the source code for org.echocat.jemoni.jmx.support.CacheDynamicMBean.java

Source

/*****************************************************************************************
 * *** BEGIN LICENSE BLOCK *****
 *
 * Version: MPL 2.0
 *
 * echocat JeMoni, Copyright (c) 2012 echocat
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * *** END LICENSE BLOCK *****
 ****************************************************************************************/

package org.echocat.jemoni.jmx.support;

import org.apache.commons.lang3.StringUtils;
import org.echocat.jomon.cache.*;
import org.echocat.jomon.runtime.iterators.CloseableIterator;
import org.echocat.jomon.runtime.util.Duration;
import org.echocat.jomon.runtime.util.ProducingType;

import javax.annotation.Nonnull;
import javax.management.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;

import static javax.management.MBeanOperationInfo.ACTION;

public class CacheDynamicMBean implements DynamicMBean {

    private final Cache<?, ?> _cache;

    public CacheDynamicMBean(@Nonnull Cache<?, ?> cache) {
        _cache = cache;
    }

    @SuppressWarnings("OverlyLongMethod")
    @Override
    public Object getAttribute(String attribute)
            throws AttributeNotFoundException, MBeanException, ReflectionException {
        final Object result;
        if ("type".equals(attribute)) {
            result = _cache.getClass().getName();
        } else if ("keyType".equals(attribute)) {
            result = _cache.getKeyType().getName();
        } else if ("valueType".equals(attribute)) {
            result = _cache.getValueType().getName();
        } else if ("size".equals(attribute)) {
            result = cast(StatisticsEnabledCache.class).size();
        } else if ("hitRatio".equals(attribute)) {
            final StatisticsEnabledCache<?, ?> statisticsEnabledCache = cast(StatisticsEnabledCache.class);
            final Long numberOfHits = statisticsEnabledCache.getNumberOfHits();
            final Long numberOfRequests = statisticsEnabledCache.getNumberOfRequests();
            if (numberOfHits != null && numberOfRequests != null) {
                result = numberOfRequests != 0 ? (double) numberOfHits / (double) numberOfRequests : 0;
            } else {
                result = null;
            }
        } else if ("dropRatio".equals(attribute)) {
            final StatisticsEnabledCache<?, ?> statisticsEnabledCache = cast(StatisticsEnabledCache.class);
            final Long numberOfDrops = statisticsEnabledCache.getNumberOfDrops();
            final Long numberOfRequests = statisticsEnabledCache.getNumberOfRequests();
            if (numberOfDrops != null && numberOfRequests != null) {
                result = numberOfRequests != 0 ? (double) numberOfDrops / (double) numberOfRequests : 0;
            } else {
                result = null;
            }
        } else if ("numberOfMisses".equals(attribute)) {
            final StatisticsEnabledCache<?, ?> statisticsEnabledCache = cast(StatisticsEnabledCache.class);
            final Long numberOfHits = statisticsEnabledCache.getNumberOfHits();
            final Long numberOfRequests = statisticsEnabledCache.getNumberOfRequests();
            if (numberOfHits != null && numberOfRequests != null) {
                result = numberOfRequests - numberOfHits;
            } else {
                result = null;
            }
        } else if ("numberOfRequests".equals(attribute)) {
            result = cast(StatisticsEnabledCache.class).getNumberOfRequests();
        } else if ("numberOfHits".equals(attribute)) {
            result = cast(StatisticsEnabledCache.class).getNumberOfHits();
        } else if ("numberOfDrops".equals(attribute)) {
            result = cast(StatisticsEnabledCache.class).getNumberOfDrops();
        } else if ("created".equals(attribute)) {
            result = cast(StatisticsEnabledCache.class).getCreated();
        } else if ("maximumLifetime".equals(attribute)) {
            final Duration maximumLifetime = cast(LimitedCache.class).getMaximumLifetime();
            result = maximumLifetime != null ? maximumLifetime.toString() : null;
        } else if ("capacity".equals(attribute)) {
            result = cast(LimitedCache.class).getCapacity();
        } else if ("producingType".equals(attribute)) {
            result = cast(ProducingTypeEnabledCache.class).getProducingType().name();
        } else if ("listeners".equals(attribute)) {
            // noinspection unchecked
            final Collection<CacheListener> listeners = cast(ListenerEnabledCache.class).getListeners();
            result = getListenersAsString(listeners);
        } else {
            throw new AttributeNotFoundException();
        }
        return result;
    }

    @Nonnull
    protected String getListenersAsString(@Nonnull Collection<CacheListener> listeners) {
        final StringBuilder sb = new StringBuilder();
        for (CacheListener listener : listeners) {
            if (sb.length() > 0) {
                sb.append('\n');
            }
            sb.append(listener);
        }
        return sb.toString();
    }

    @Override
    public void setAttribute(Attribute attribute)
            throws AttributeNotFoundException, InvalidAttributeValueException, MBeanException, ReflectionException {
        final String attributeName = attribute.getName();
        final Object value = attribute.getValue();
        if ("maximumLifetime".equals(attributeName)) {
            if (value != null && !(value instanceof String)) {
                throw new InvalidAttributeValueException();
            }
            cast(LimitedCache.class).setMaximumLifetime(
                    value != null && !value.toString().trim().isEmpty() ? new Duration(value.toString()) : null);
        } else if ("capacity".equals(attributeName)) {
            if (value != null && !(value instanceof Number)) {
                throw new InvalidAttributeValueException();
            }
            cast(LimitedCache.class).setCapacity(value != null ? ((Number) value).longValue() : null);
        } else if ("producingType".equals(attributeName)) {
            if (value != null && !(value instanceof String)) {
                throw new InvalidAttributeValueException();
            }
            final ProducingType producingType;
            if (value == null || value.toString().trim().isEmpty()) {
                producingType = ProducingType.DEFAULT;
            } else {
                try {
                    producingType = ProducingType.valueOf(value.toString().trim());
                } catch (IllegalArgumentException ignored) {
                    throw new InvalidAttributeValueException("Illegal value: " + value + ". Possible values: "
                            + StringUtils.join(ProducingType.values(), ", "));
                }
            }
            cast(ProducingTypeEnabledCache.class).setProducingType(producingType);
        } else {
            throw new AttributeNotFoundException();
        }
    }

    @Override
    public Object invoke(String actionName, Object[] params, String[] signature)
            throws MBeanException, ReflectionException {
        final Object result;
        if ("clear".equals(actionName) && _cache instanceof ClearableCache) {
            ((ClearableCache<?, ?>) _cache).clear();
            result = null;
        } else if ("resetStatistics".equals(actionName) && _cache instanceof StatisticsEnabledCache) {
            ((StatisticsEnabledCache<?, ?>) _cache).resetStatistics();
            result = null;
        } else if ("getListeners".equals(actionName) && _cache instanceof ListenerEnabledCache) {
            // noinspection unchecked
            result = getListenersAsString(((ListenerEnabledCache) _cache).getListeners());
        } else if ("getKeys".equals(actionName) && _cache instanceof KeysEnabledCache) {
            // noinspection unchecked
            try (final CloseableIterator<Object> iterator = ((KeysEnabledCache<Object, ?>) _cache).iterator()) {
                final StringBuilder sb = new StringBuilder();
                if (params.length > 0 && params[0] instanceof Number && ((Number) params[0]).intValue() >= 0) {
                    final int limit = ((Number) params[0]).intValue();
                    for (int i = 0; iterator.hasNext() && i < limit; i++) {
                        if (sb.length() > 0) {
                            sb.append('\n');
                        }
                        sb.append(iterator.next());
                    }
                } else {
                    while (iterator.hasNext()) {
                        if (sb.length() > 0) {
                            sb.append('\n');
                        }
                        sb.append(iterator.next());
                    }
                }
                result = sb.toString();
            }
        } else if ("get".equals(actionName)) {
            final String key = params.length > 0 && params[0] != null ? params[0].toString() : null;
            // noinspection unchecked
            final Object plainResult = ((Cache<String, Object>) _cache).get(key);
            result = plainResult != null ? plainResult.toString() : null;
        } else if ("remove".equals(actionName)) {
            final String key = params.length > 0 && params[0] != null ? params[0].toString() : null;
            // noinspection unchecked
            ((Cache<String, Object>) _cache).remove(key);
            result = null;
        } else if ("contains".equals(actionName)) {
            final String key = params.length > 0 && params[0] != null ? params[0].toString() : null;
            // noinspection unchecked
            result = ((Cache<String, Object>) _cache).contains(key);
        } else {
            throw new UnsupportedOperationException();
        }
        return result;
    }

    @Override
    public MBeanInfo getMBeanInfo() {
        return new MBeanInfo(_cache.getClass().getName(), null, getAttributes(), null, getOperations(), null);
    }

    @Nonnull
    protected MBeanAttributeInfo[] getAttributes() {
        final List<MBeanAttributeInfo> result = new ArrayList<>();
        result.add(new MBeanAttributeInfo("type", String.class.getName(), null, true, false, false));
        result.add(new MBeanAttributeInfo("keyType", String.class.getName(), null, true, false, false));
        result.add(new MBeanAttributeInfo("valueType", String.class.getName(), null, true, false, false));
        if (_cache instanceof StatisticsEnabledCache) {
            result.add(new MBeanAttributeInfo("size", Long.class.getName(), null, true, false, false));
            result.add(new MBeanAttributeInfo("hitRatio", Double.class.getName(), null, true, false, false));
            result.add(new MBeanAttributeInfo("dropRatio", Double.class.getName(), null, true, false, false));
            result.add(new MBeanAttributeInfo("numberOfRequests", Long.class.getName(), null, true, false, false));
            result.add(new MBeanAttributeInfo("numberOfHits", Long.class.getName(), null, true, false, false));
            result.add(new MBeanAttributeInfo("numberOfDrops", Long.class.getName(), null, true, false, false));
            result.add(new MBeanAttributeInfo("numberOfMisses", Long.class.getName(), null, true, false, false));
            result.add(new MBeanAttributeInfo("created", Date.class.getName(), null, true, false, false));
        }
        if (_cache instanceof LimitedCache) {
            result.add(new MBeanAttributeInfo("maximumLifetime", String.class.getName(), null, true, true, false));
            result.add(new MBeanAttributeInfo("capacity", Long.class.getName(), null, true, true, false));
        }
        if (_cache instanceof ListenerEnabledCache) {
            result.add(new MBeanAttributeInfo("listeners", String.class.getName(), null, true, false, false));
        }
        if (_cache instanceof ProducingTypeEnabledCache) {
            result.add(new MBeanAttributeInfo("producingType", String.class.getName(), null, true, true, false));
        }
        return result.toArray(new MBeanAttributeInfo[result.size()]);
    }

    @Nonnull
    protected MBeanOperationInfo[] getOperations() {
        final List<MBeanOperationInfo> result = new ArrayList<>();
        result.add(new MBeanOperationInfo("get", null,
                new MBeanParameterInfo[] { new MBeanParameterInfo("key", String.class.getName(), null) },
                String.class.getName(), ACTION));
        result.add(new MBeanOperationInfo("remove", null,
                new MBeanParameterInfo[] { new MBeanParameterInfo("key", String.class.getName(), null) },
                Void.TYPE.getName(), ACTION));
        result.add(new MBeanOperationInfo("contains", null,
                new MBeanParameterInfo[] { new MBeanParameterInfo("key", String.class.getName(), null) },
                Boolean.TYPE.getName(), ACTION));
        if (_cache instanceof KeysEnabledCache) {
            result.add(new MBeanOperationInfo("getKeys", null,
                    new MBeanParameterInfo[] { new MBeanParameterInfo("limit", Integer.class.getName(), null) },
                    String.class.getName(), ACTION));
        }
        if (_cache instanceof ClearableCache) {
            result.add(
                    new MBeanOperationInfo("clear", null, new MBeanParameterInfo[0], Void.TYPE.getName(), ACTION));
        }
        if (_cache instanceof StatisticsEnabledCache) {
            result.add(new MBeanOperationInfo("resetStatistics", null, new MBeanParameterInfo[0],
                    Void.TYPE.getName(), ACTION));
        }
        if (_cache instanceof ListenerEnabledCache) {
            result.add(new MBeanOperationInfo("getListeners", null, new MBeanParameterInfo[0],
                    String.class.getName(), ACTION));
        }
        return result.toArray(new MBeanOperationInfo[result.size()]);
    }

    @Nonnull
    protected <T extends Cache<?, ?>> T cast(@Nonnull Class<T> type) throws AttributeNotFoundException {
        if (type.isInstance(_cache)) {
            return type.cast(_cache);
        } else {
            throw new AttributeNotFoundException();
        }
    }

    @Override
    public AttributeList getAttributes(String[] attributes) {
        throw new UnsupportedOperationException();
    }

    @Override
    public AttributeList setAttributes(AttributeList attributes) {
        throw new UnsupportedOperationException();
    }
}