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.activemq.transport;
018    
019    import java.lang.ref.WeakReference;
020    import java.util.Collections;
021    import java.util.HashSet;
022    import java.util.Set;
023    
024    import javax.management.ObjectName;
025    
026    import org.apache.activemq.broker.jmx.AnnotatedMBean;
027    import org.apache.activemq.broker.jmx.ManagementContext;
028    import org.apache.activemq.util.JMXSupport;
029    import org.slf4j.Logger;
030    import org.slf4j.LoggerFactory;
031    
032    /**
033     * Class implementing the TransportLoggerViewMBean interface.
034     * When an object of this class is created, it registers itself in
035     * the MBeanServer of the management context provided.
036     * When a TransportLogger object is finalized because the Transport Stack
037     * where it resides is no longer in use, the method unregister() will be called.
038     * 
039     * @author David Martin Clavo david(dot)martin(dot)clavo(at)gmail.com
040     *  
041     * @see TransportLoggerViewMBean.
042     */
043    public class TransportLoggerView implements TransportLoggerViewMBean {
044    
045        private static final Logger log = LoggerFactory.getLogger(TransportLoggerView.class);
046        
047        /**
048         * Set with the TransportLoggerViews objects created.
049         * Used by the methods enableAllTransportLoggers and diablellTransportLoggers.
050         * The method unregister() removes objects from this set.
051         */
052        private static Set<TransportLoggerView> transportLoggerViews = Collections.synchronizedSet(new HashSet<TransportLoggerView>());
053    
054        private final WeakReference<TransportLogger> transportLogger;
055        private final String nextTransportName;
056        private final int id;
057        private final ManagementContext managementContext;
058        private final ObjectName name;
059    
060        /**
061         * Constructor.
062         * @param transportLogger The TransportLogger object which is to be managed by this MBean.
063         * @param nextTransportName The name of the next TransportLayer. This is used to give a unique
064         * name for each MBean of the TransportLoggerView class.
065         * @param id The id of the TransportLogger to be watched.
066         * @param managementContext The management context who has the MBeanServer where this MBean will be registered.
067         */
068        public TransportLoggerView (TransportLogger transportLogger, String nextTransportName, int id, ManagementContext managementContext) {
069            this.transportLogger = new WeakReference<TransportLogger>(transportLogger);
070            this.nextTransportName = nextTransportName;
071            this.id = id;
072            this.managementContext = managementContext;
073            this.name = this.createTransportLoggerObjectName();
074            
075            TransportLoggerView.transportLoggerViews.add(this);
076            this.register();
077        }
078        
079        /**
080         * Enable logging for all Transport Loggers at once.
081         */
082        public static void enableAllTransportLoggers() {
083            for (TransportLoggerView view : transportLoggerViews) {
084                view.enableLogging();
085            }
086        }
087        
088        /**
089         * Disable logging for all Transport Loggers at once.
090         */
091        public static void disableAllTransportLoggers() {
092            for (TransportLoggerView view : transportLoggerViews) {
093                view.disableLogging();
094            }
095        }
096    
097        // doc comment inherited from TransportLoggerViewMBean
098        public void enableLogging() {
099            this.setLogging(true);
100        }
101    
102        // doc comment inherited from TransportLoggerViewMBean
103        public void disableLogging() {
104            this.setLogging(false);
105        }   
106    
107        // doc comment inherited from TransportLoggerViewMBean
108        public boolean isLogging() {
109            return transportLogger.get().isLogging();
110        }
111    
112        // doc comment inherited from TransportLoggerViewMBean
113        public void setLogging(boolean logging) {
114            transportLogger.get().setLogging(logging);
115        }
116    
117        /**
118         * Registers this MBean in the MBeanServer of the management context
119         * provided at creation time. This method is only called by the constructor.
120         */
121        private void register() {
122            try {
123                    AnnotatedMBean.registerMBean(this.managementContext, this, this.name);
124            } catch (Exception e) {
125                log.error("Could not register MBean for TransportLoggerView " + id + "with name " + this.name.toString() + ", reason: " + e, e);
126            }
127    
128        }
129    
130        /**
131         * Unregisters the MBean from the MBeanServer of the management context
132         * provided at creation time.
133         * This method is called by the TransportLogger object being managed when
134         * the TransportLogger object is finalized, to avoid the memory leak that
135         * would be caused if MBeans were not unregistered. 
136         */
137        public void unregister() {
138            
139            TransportLoggerView.transportLoggerViews.remove(this);
140            
141            try {
142                this.managementContext.unregisterMBean(this.name);
143            } catch (Exception e) {
144                log.error("Could not unregister MBean for TransportLoggerView " + id + "with name " + this.name.toString() + ", reason: " + e, e);
145            }
146        }
147    
148        /**
149         * Creates the ObjectName to be used when registering the MBean.
150         * @return the ObjectName to be used when registering the MBean.
151         */
152        private ObjectName createTransportLoggerObjectName()  {
153            try {
154                return new ObjectName(
155                        createTransportLoggerObjectNameRoot(this.managementContext)
156                        + JMXSupport.encodeObjectNamePart(TransportLogger.class.getSimpleName()
157                                + " " + this.id + ";" + this.nextTransportName));
158            } catch (Exception e) {
159                log.error("Could not create ObjectName for TransportLoggerView " + id + ", reason: " + e, e);
160                return null;
161            }
162        }
163    
164        /**
165         * Creates the part of the ObjectName that will be used by all MBeans.
166         * This method is public so it can be used by the TransportLoggerControl class.
167         * @param managementContext
168         * @return A String with the part of the ObjectName common to all the TransportLoggerView MBeans.
169         */
170        public static String createTransportLoggerObjectNameRoot(ManagementContext managementContext) {
171            return managementContext.getJmxDomainName()+":"+"Type=TransportLogger,"+"TransportLoggerName=";
172        }
173    
174    }