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 */
017package org.apache.activemq.transport;
018
019import java.lang.ref.WeakReference;
020import java.util.Collections;
021import java.util.HashSet;
022import java.util.Set;
023
024import javax.management.ObjectName;
025
026import org.apache.activemq.broker.jmx.AnnotatedMBean;
027import org.apache.activemq.broker.jmx.ManagementContext;
028import org.apache.activemq.util.JMXSupport;
029import org.slf4j.Logger;
030import 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 */
043public 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}