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     */
017    package org.apache.servicemix.web.jmx;
018    
019    import org.apache.activemq.Service;
020    import org.apache.commons.logging.Log;
021    import org.apache.commons.logging.LogFactory;
022    
023    import javax.jms.JMSException;
024    import javax.management.JMException;
025    import javax.management.MBeanServer;
026    import javax.management.MBeanServerFactory;
027    import javax.management.MalformedObjectNameException;
028    import javax.management.ObjectName;
029    
030    import java.util.List;
031    
032    /**
033     * A Flow provides different dispatch policies within the NMR
034     *
035     * @version $Revision: 356583 $
036     */
037    public class ManagementContext implements Service {
038        /**
039         * Default servicemix domain
040         */
041        public static String DEFAULT_DOMAIN = "org.apache.activemq";
042    
043        private final static Log log = LogFactory.getLog(ManagementContext.class);
044    
045        private MBeanServer beanServer;
046        private String jmxDomainName = DEFAULT_DOMAIN;
047        private boolean useMBeanServer = true;
048        private boolean createMBeanServer = true;
049        private boolean locallyCreateMBeanServer = false;
050    
051        public ManagementContext() {
052            this(null);
053        }
054    
055        public ManagementContext(MBeanServer server) {
056            this.beanServer = server;
057        }
058    
059        public void start() throws JMSException {
060            // lets force the MBeanServer to be created if needed
061            getMBeanServer();
062        }
063    
064        public void stop() throws JMSException {
065            if (locallyCreateMBeanServer && beanServer != null) {
066                // check to see if the factory knows about this server
067                List list = MBeanServerFactory.findMBeanServer(null);
068                if (list != null && !list.isEmpty() && list.contains(beanServer)) {
069                    MBeanServerFactory.releaseMBeanServer(beanServer);
070                }
071            }
072        }
073    
074        /**
075         * @return Returns the jmxDomainName.
076         */
077        public String getJmxDomainName() {
078            return jmxDomainName;
079        }
080    
081        /**
082         * @param jmxDomainName
083         *            The jmxDomainName to set.
084         */
085        public void setJmxDomainName(String jmxDomainName) {
086            this.jmxDomainName = jmxDomainName;
087        }
088    
089        /**
090         * Get the MBeanServer
091         *
092         * @return the MBeanServer
093         */
094        public MBeanServer getMBeanServer() {
095            if (this.beanServer == null) {
096                this.beanServer = findMBeanServer();
097            }
098            return beanServer;
099        }
100    
101        /**
102         * @return Returns the useMBeanServer.
103         */
104        public boolean isUseMBeanServer() {
105            return useMBeanServer;
106        }
107    
108        /**
109         * @param useMBeanServer
110         *            The useMBeanServer to set.
111         */
112        public void setUseMBeanServer(boolean useMBeanServer) {
113            this.useMBeanServer = useMBeanServer;
114        }
115    
116        /**
117         * @return Returns the createMBeanServer flag.
118         */
119        public boolean isCreateMBeanServer() {
120            return createMBeanServer;
121        }
122    
123        /**
124         * @param enableJMX
125         *            Set createMBeanServer.
126         */
127        public void setCreateMBeanServer(boolean enableJMX) {
128            this.createMBeanServer = enableJMX;
129        }
130    
131        /**
132         * Formulate and return the MBean ObjectName of a custom control MBean
133         *
134         * @param type
135         * @param name
136         * @return the JMX ObjectName of the MBean, or <code>null</code> if
137         *         <code>customName</code> is invalid.
138         */
139        public ObjectName createCustomComponentMBeanName(String type, String name) {
140            ObjectName result = null;
141            String tmp = jmxDomainName + ":" + "type=" + sanitizeString(type) + ",name=" + sanitizeString(name);
142            try {
143                result = new ObjectName(tmp);
144            }
145            catch (MalformedObjectNameException e) {
146                log.error("Couldn't create ObjectName from: " + type + " , " + name);
147            }
148            return result;
149        }
150    
151        /**
152         * The ':' and '/' characters are reserved in ObjectNames
153         *
154         * @param in
155         * @return sanitized String
156         */
157        private static String sanitizeString(String in) {
158            String result = null;
159            if (in != null) {
160                result = in.replace(':', '_');
161                result = result.replace('/', '_');
162                result = result.replace('\\', '_');
163            }
164            return result;
165        }
166    
167        /**
168         * Retrive an System ObjectName
169         *
170         * @param domainName
171         * @param containerName
172         * @param theClass
173         * @return the ObjectName
174         * @throws MalformedObjectNameException
175         */
176        public static ObjectName getSystemObjectName(String domainName, String containerName, Class theClass)
177                throws MalformedObjectNameException, NullPointerException {
178            String tmp = domainName + ":" + "type=" + theClass.getName() + ",name="
179                    + getRelativeName(containerName, theClass);
180            return new ObjectName(tmp);
181        }
182    
183        private static String getRelativeName(String containerName, Class theClass) {
184            String name = theClass.getName();
185            int index = name.lastIndexOf(".");
186            if (index >= 0 && (index + 1) < name.length()) {
187                name = name.substring(index + 1);
188            }
189            return containerName + "." + name;
190        }
191    
192        /**
193         * Unregister an MBean
194         *
195         * @param name
196         * @throws JMException
197         */
198        public void unregisterMBean(ObjectName name) throws JMException {
199            if (beanServer != null && beanServer.isRegistered(name)) {
200                beanServer.unregisterMBean(name);
201            }
202        }
203    
204        protected synchronized MBeanServer findMBeanServer() {
205            MBeanServer result = null;
206            // create the mbean server
207            try {
208                if (useMBeanServer) {
209                    // lets piggy back on another MBeanServer -
210                    // we could be in an appserver!
211                    List list = MBeanServerFactory.findMBeanServer(null);
212                    if (list != null && list.size() > 0) {
213                        result = (MBeanServer) list.get(0);
214                    }
215                }
216    
217                if (result == null && createMBeanServer) {
218                    result = MBeanServerFactory.createMBeanServer(jmxDomainName);
219                    locallyCreateMBeanServer = true;
220                }
221            }
222            catch (NoClassDefFoundError e) {
223                log.error("Couldnot load MBeanServer", e);
224            }
225            catch (Throwable e) {
226                // probably don't have access to system properties
227                log.error("Failed to initialize MBeanServer", e);
228            }
229            return result;
230        }
231    }