001    /**
002     *
003     * Licensed to the Apache Software Foundation (ASF) under one or more
004     * contributor license agreements.  See the NOTICE file distributed with
005     * this work for additional information regarding copyright ownership.
006     * The ASF licenses this file to You under the Apache License, Version 2.0
007     * (the "License"); you may not use this file except in compliance with
008     * 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, software
013     * distributed under the License is distributed on an "AS IS" BASIS,
014     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015     * See the License for the specific language governing permissions and
016     * limitations under the License.
017     */
018    package org.apache.camel.management;
019    
020    import java.util.HashSet;
021    import java.util.Set;
022    
023    import javax.management.InstanceAlreadyExistsException;
024    import javax.management.JMException;
025    import javax.management.MBeanServer;
026    import javax.management.NotCompliantMBeanException;
027    import javax.management.ObjectInstance;
028    import javax.management.ObjectName;
029    import javax.management.modelmbean.InvalidTargetObjectTypeException;
030    import javax.management.modelmbean.ModelMBeanInfo;
031    import javax.management.modelmbean.RequiredModelMBean;
032    
033    import org.apache.camel.CamelContext;
034    import org.apache.camel.CamelContextAware;
035    import org.apache.camel.InstrumentationAgent;
036    import org.apache.camel.impl.DefaultCamelContext;
037    import org.springframework.jmx.export.annotation.AnnotationJmxAttributeSource;
038    import org.springframework.jmx.export.assembler.MetadataMBeanInfoAssembler;
039    
040    public class InstrumentationAgentImpl implements InstrumentationAgent, CamelContextAware {
041    
042            private MBeanServer server;
043            private CamelContext context;
044        private Set<ObjectName> mbeans = new HashSet<ObjectName>();
045        MetadataMBeanInfoAssembler assembler;
046            
047        public InstrumentationAgentImpl() {
048            assembler = new MetadataMBeanInfoAssembler();
049            assembler.setAttributeSource(new AnnotationJmxAttributeSource());
050        }
051            public CamelContext getCamelContext() {
052                    return context;
053            }
054    
055            public void setCamelContext(CamelContext camelContext) {
056                    context = camelContext;
057            }
058    
059            public void setMBeanServer(MBeanServer server) {
060                    this.server = server;
061            }
062            
063            public MBeanServer getMBeanServer() {
064                    return server;
065            }
066    
067            public void register(Object obj, ObjectName name) throws JMException {
068                    register(obj, name, false);
069            }
070    
071            public void register(Object obj, ObjectName name, boolean forceRegistration) throws JMException {
072            try {
073                registerMBeanWithServer(obj, name, forceRegistration);           
074            } catch (NotCompliantMBeanException e) {        
075                //If this is not a "normal" MBean, then try to deploy it using JMX annotations
076                    ModelMBeanInfo mbi = null;
077                    mbi = assembler.getMBeanInfo(obj, name.toString());
078                RequiredModelMBean mbean = (RequiredModelMBean)server.instantiate(RequiredModelMBean.class.getName());
079                mbean.setModelMBeanInfo(mbi);
080                try {
081                    mbean.setManagedResource(obj, "ObjectReference");
082                } catch (InvalidTargetObjectTypeException itotex) {
083                    throw new JMException(itotex.getMessage());
084                }
085                registerMBeanWithServer(mbean, name, forceRegistration);
086            }                
087            }
088    
089            public void unregister(ObjectName name) throws JMException {
090            }
091    
092            public void start() {
093                    if (context == null) {
094                            // LOG warning
095                            return;
096                    }
097                    
098                    if (context instanceof DefaultCamelContext) {
099                            DefaultCamelContext dc = (DefaultCamelContext)context;
100                            InstrumentationLifecycleStrategy ls = new InstrumentationLifecycleStrategy(this); 
101                            dc.setLifecycleStrategy(ls);
102                            ls.onContextCreate(context);
103                    }
104            }
105            
106        public void stop() {
107            //Using the array to hold the busMBeans to avoid the CurrentModificationException
108            Object[] mBeans = mbeans.toArray();
109            for (Object name : mBeans) {
110                    mbeans.remove((ObjectName)name);
111                try {
112                    unregister((ObjectName)name);
113                } catch (JMException jmex) {
114                    // log
115                }
116            }
117        }
118        
119        private void registerMBeanWithServer(Object obj, ObjectName name, boolean forceRegistration) 
120                    throws JMException {
121            
122                ObjectInstance instance = null;
123                try {
124                    instance = server.registerMBean(obj, name);           
125                } catch (InstanceAlreadyExistsException e) {            
126                    if (forceRegistration) {
127                            server.unregisterMBean(name);               
128                        instance = server.registerMBean(obj, name);
129                    } else {
130                        throw e;
131                    }
132                }
133                
134                if (instance != null) {
135                    mbeans.add(name);
136                }
137        }
138    }