001/*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *   http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing,
013 * software distributed under the License is distributed on an
014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 * KIND, either express or implied.  See the License for the
016 * specific language governing permissions and limitations
017 * under the License.
018 */
019package org.apache.commons.jcs.jcache.jmx;
020
021import javax.management.ListenerNotFoundException;
022import javax.management.MBeanNotificationInfo;
023import javax.management.MBeanServer;
024import javax.management.MBeanServerBuilder;
025import javax.management.MBeanServerDelegate;
026import javax.management.Notification;
027import javax.management.NotificationFilter;
028import javax.management.NotificationListener;
029import java.util.concurrent.ConcurrentHashMap;
030import java.util.concurrent.ConcurrentMap;
031
032public class ConfigurableMBeanServerIdBuilder extends MBeanServerBuilder
033{
034    private static ConcurrentMap<Key, MBeanServer> JVM_SINGLETONS = new ConcurrentHashMap<Key, MBeanServer>();
035
036    private static class Key
037    {
038        private final String domain;
039        private final MBeanServer outer;
040
041        private Key(final String domain, final MBeanServer outer)
042        {
043            this.domain = domain;
044            this.outer = outer;
045        }
046
047        @Override
048        public boolean equals(final Object o)
049        {
050            if (this == o)
051                return true;
052            if (o == null || getClass() != o.getClass())
053                return false;
054
055            final Key key = Key.class.cast(o);
056            return !(domain != null ? !domain.equals(key.domain) : key.domain != null)
057                    && !(outer != null ? !outer.equals(key.outer) : key.outer != null);
058
059        }
060
061        @Override
062        public int hashCode()
063        {
064            int result = domain != null ? domain.hashCode() : 0;
065            result = 31 * result + (outer != null ? outer.hashCode() : 0);
066            return result;
067        }
068    }
069
070    @Override
071    public MBeanServer newMBeanServer(final String defaultDomain, final MBeanServer outer, final MBeanServerDelegate delegate)
072    {
073        final Key key = new Key(defaultDomain, outer);
074        MBeanServer server = JVM_SINGLETONS.get(key);
075        if (server == null)
076        {
077            server = super.newMBeanServer(defaultDomain, outer, new ForceIdMBeanServerDelegate(delegate));
078            final MBeanServer existing = JVM_SINGLETONS.putIfAbsent(key, server);
079            if (existing != null)
080            {
081                server = existing;
082            }
083        }
084        return server;
085    }
086
087    private class ForceIdMBeanServerDelegate extends MBeanServerDelegate
088    {
089        private final MBeanServerDelegate delegate;
090
091        public ForceIdMBeanServerDelegate(final MBeanServerDelegate delegate)
092        {
093            this.delegate = delegate;
094        }
095
096        @Override
097        public String getMBeanServerId()
098        {
099            return System.getProperty("org.jsr107.tck.management.agentId", delegate.getMBeanServerId());
100        }
101
102        @Override
103        public String getSpecificationName()
104        {
105            return delegate.getSpecificationName();
106        }
107
108        @Override
109        public String getSpecificationVersion()
110        {
111            return delegate.getSpecificationVersion();
112        }
113
114        @Override
115        public String getSpecificationVendor()
116        {
117            return delegate.getSpecificationVendor();
118        }
119
120        @Override
121        public String getImplementationName()
122        {
123            return delegate.getImplementationName();
124        }
125
126        @Override
127        public String getImplementationVersion()
128        {
129            return delegate.getImplementationVersion();
130        }
131
132        @Override
133        public String getImplementationVendor()
134        {
135            return delegate.getImplementationVendor();
136        }
137
138        @Override
139        public MBeanNotificationInfo[] getNotificationInfo()
140        {
141            return delegate.getNotificationInfo();
142        }
143
144        @Override
145        public void addNotificationListener(final NotificationListener listener, final NotificationFilter filter, final Object handback)
146                throws IllegalArgumentException
147        {
148            delegate.addNotificationListener(listener, filter, handback);
149        }
150
151        @Override
152        public void removeNotificationListener(final NotificationListener listener, final NotificationFilter filter, final Object handback)
153                throws ListenerNotFoundException
154        {
155            delegate.removeNotificationListener(listener, filter, handback);
156        }
157
158        @Override
159        public void removeNotificationListener(final NotificationListener listener) throws ListenerNotFoundException
160        {
161            delegate.removeNotificationListener(listener);
162        }
163
164        @Override
165        public void sendNotification(final Notification notification)
166        {
167            delegate.sendNotification(notification);
168        }
169    }
170}