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.jcs3.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 final ConcurrentMap<Key, MBeanServer> JVM_SINGLETONS = new ConcurrentHashMap<>();
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            }
053            if (o == null || getClass() != o.getClass()) {
054                return false;
055            }
056
057            final Key key = Key.class.cast(o);
058            return !(domain != null ? !domain.equals(key.domain) : key.domain != null)
059                    && !(outer != null ? !outer.equals(key.outer) : key.outer != null);
060
061        }
062
063        @Override
064        public int hashCode()
065        {
066            int result = domain != null ? domain.hashCode() : 0;
067            result = 31 * result + (outer != null ? outer.hashCode() : 0);
068            return result;
069        }
070    }
071
072    @Override
073    public MBeanServer newMBeanServer(final String defaultDomain, final MBeanServer outer, final MBeanServerDelegate delegate)
074    {
075        final Key key = new Key(defaultDomain, outer);
076        MBeanServer server = JVM_SINGLETONS.get(key);
077        if (server == null)
078        {
079            server = super.newMBeanServer(defaultDomain, outer, new ForceIdMBeanServerDelegate(delegate));
080            final MBeanServer existing = JVM_SINGLETONS.putIfAbsent(key, server);
081            if (existing != null)
082            {
083                server = existing;
084            }
085        }
086        return server;
087    }
088
089    private class ForceIdMBeanServerDelegate extends MBeanServerDelegate
090    {
091        private final MBeanServerDelegate delegate;
092
093        public ForceIdMBeanServerDelegate(final MBeanServerDelegate delegate)
094        {
095            this.delegate = delegate;
096        }
097
098        @Override
099        public String getMBeanServerId()
100        {
101            return System.getProperty("org.jsr107.tck.management.agentId", delegate.getMBeanServerId());
102        }
103
104        @Override
105        public String getSpecificationName()
106        {
107            return delegate.getSpecificationName();
108        }
109
110        @Override
111        public String getSpecificationVersion()
112        {
113            return delegate.getSpecificationVersion();
114        }
115
116        @Override
117        public String getSpecificationVendor()
118        {
119            return delegate.getSpecificationVendor();
120        }
121
122        @Override
123        public String getImplementationName()
124        {
125            return delegate.getImplementationName();
126        }
127
128        @Override
129        public String getImplementationVersion()
130        {
131            return delegate.getImplementationVersion();
132        }
133
134        @Override
135        public String getImplementationVendor()
136        {
137            return delegate.getImplementationVendor();
138        }
139
140        @Override
141        public MBeanNotificationInfo[] getNotificationInfo()
142        {
143            return delegate.getNotificationInfo();
144        }
145
146        @Override
147        public void addNotificationListener(final NotificationListener listener, final NotificationFilter filter, final Object handback)
148                throws IllegalArgumentException
149        {
150            delegate.addNotificationListener(listener, filter, handback);
151        }
152
153        @Override
154        public void removeNotificationListener(final NotificationListener listener, final NotificationFilter filter, final Object handback)
155                throws ListenerNotFoundException
156        {
157            delegate.removeNotificationListener(listener, filter, handback);
158        }
159
160        @Override
161        public void removeNotificationListener(final NotificationListener listener) throws ListenerNotFoundException
162        {
163            delegate.removeNotificationListener(listener);
164        }
165
166        @Override
167        public void sendNotification(final Notification notification)
168        {
169            delegate.sendNotification(notification);
170        }
171    }
172}