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.activemq.gbean.management;
019    
020    import java.util.ArrayList;
021    import java.util.Iterator;
022    import java.util.List;
023    import java.util.Set;
024    
025    import org.apache.activemq.gbean.ActiveMQBroker;
026    import org.apache.activemq.gbean.ActiveMQConnector;
027    import org.apache.activemq.gbean.ActiveMQManager;
028    import org.apache.activemq.gbean.TransportConnectorGBeanImpl;
029    import org.apache.commons.logging.Log;
030    import org.apache.commons.logging.LogFactory;
031    import org.apache.geronimo.gbean.AbstractName;
032    import org.apache.geronimo.gbean.AbstractNameQuery;
033    import org.apache.geronimo.gbean.GBeanData;
034    import org.apache.geronimo.gbean.GBeanInfo;
035    import org.apache.geronimo.gbean.GBeanInfoBuilder;
036    import org.apache.geronimo.gbean.ReferencePatterns;
037    import org.apache.geronimo.j2ee.j2eeobjectnames.NameFactory;
038    import org.apache.geronimo.kernel.GBeanNotFoundException;
039    import org.apache.geronimo.kernel.Kernel;
040    import org.apache.geronimo.kernel.config.ConfigurationUtil;
041    import org.apache.geronimo.kernel.config.EditableConfigurationManager;
042    import org.apache.geronimo.kernel.config.InvalidConfigException;
043    import org.apache.geronimo.kernel.proxy.ProxyManager;
044    import org.apache.geronimo.management.geronimo.JMSBroker;
045    import org.apache.geronimo.management.geronimo.JMSConnector;
046    import org.apache.geronimo.management.geronimo.NetworkConnector;
047    
048    /**
049     * Implementation of the ActiveMQ management interface.  These are the ActiveMQ
050     * management features available at runtime.
051     *
052     * @version $Revision: 1.0$
053     */
054    public class ActiveMQManagerGBean implements ActiveMQManager {
055        private static final Log log = LogFactory.getLog(ActiveMQManagerGBean.class.getName());
056        private Kernel kernel;
057        private String objectName;
058    
059        public ActiveMQManagerGBean(Kernel kernel, String objectName) {
060            this.kernel = kernel;
061            this.objectName = objectName;
062        }
063    
064        public String getProductName() {
065            return "ActiveMQ";
066        }
067    
068        public String getObjectName() {
069            return objectName;
070        }
071    
072        public boolean isEventProvider() {
073            return false;
074        }
075    
076        public boolean isStateManageable() {
077            return true;
078        }
079    
080        public boolean isStatisticsProvider() {
081            return false;
082        }
083    
084        public Object[] getContainers() {
085            ProxyManager proxyManager = kernel.getProxyManager();
086            AbstractNameQuery query = new AbstractNameQuery(ActiveMQBroker.class.getName());
087            Set names = kernel.listGBeans(query);
088            ActiveMQBroker[] results = new ActiveMQBroker[names.size()];
089            int i=0;
090            for (Iterator it = names.iterator(); it.hasNext(); i++) {
091                AbstractName name = (AbstractName) it.next();
092                results[i] = (ActiveMQBroker) proxyManager.createProxy(name, ActiveMQBroker.class.getClassLoader());
093            }
094            return results;
095        }
096    
097        public String[] getSupportedProtocols() {
098            // see files in modules/core/src/conf/META-INF/services/org/activemq/transport/server/
099            return new String[]{ "tcp", "stomp", "vm", "peer", "udp", "multicast", "failover"};
100        }
101    
102        public NetworkConnector[] getConnectors() {
103            ProxyManager proxyManager = kernel.getProxyManager();
104            AbstractNameQuery query = new AbstractNameQuery(ActiveMQConnector.class.getName());
105            Set names = kernel.listGBeans(query);
106            ActiveMQConnector[] results = new ActiveMQConnector[names.size()];
107            int i=0;
108            for (Iterator it = names.iterator(); it.hasNext(); i++) {
109                AbstractName name = (AbstractName) it.next();
110                results[i] = (ActiveMQConnector) proxyManager.createProxy(name, ActiveMQConnector.class.getClassLoader());
111            }
112            return results;
113        }
114    
115        public NetworkConnector[] getConnectors(String protocol) {
116            if(protocol == null) {
117                return getConnectors();
118            }
119            List result = new ArrayList();
120            ProxyManager proxyManager = kernel.getProxyManager();
121            AbstractNameQuery query = new AbstractNameQuery(ActiveMQConnector.class.getName());
122            Set names = kernel.listGBeans(query);
123            for (Iterator it = names.iterator(); it.hasNext();) {
124                AbstractName name = (AbstractName) it.next();
125                try {
126                    if (kernel.getAttribute(name, "protocol").equals(protocol)) {
127                        result.add(proxyManager.createProxy(name, ActiveMQConnector.class.getClassLoader()));
128                    }
129                } catch (Exception e) {
130                    log.error("Unable to check the protocol for a connector", e);
131                }
132            }
133            return (ActiveMQConnector[]) result.toArray(new ActiveMQConnector[names.size()]);
134        }
135    
136        public NetworkConnector[] getConnectorsForContainer(Object broker) {
137            AbstractName containerName = kernel.getAbstractNameFor(broker);
138            ProxyManager mgr = kernel.getProxyManager();
139            try {
140                List results = new ArrayList();
141                AbstractNameQuery query = new AbstractNameQuery(ActiveMQConnector.class.getName());
142                Set set = kernel.listGBeans(query); // all Jetty connectors
143                for (Iterator it = set.iterator(); it.hasNext();) {
144                    AbstractName name = (AbstractName) it.next(); // a single Jetty connector
145                    GBeanData data = kernel.getGBeanData(name);
146                    ReferencePatterns refs = data.getReferencePatterns("brokerService");
147                    if (containerName.equals(refs.getAbstractName())) {
148                        results.add(mgr.createProxy(name, ActiveMQConnector.class.getClassLoader()));
149                    }
150                }
151                return (ActiveMQConnector[]) results.toArray(new ActiveMQConnector[results.size()]);
152            } catch (Exception e) {
153                throw (IllegalArgumentException) new IllegalArgumentException("Unable to look up connectors for ActiveMQ broker '"+containerName).initCause(e);
154            }
155        }
156    
157        public NetworkConnector[] getConnectorsForContainer(Object broker, String protocol) {
158            if(protocol == null) {
159                return getConnectorsForContainer(broker);
160            }
161            AbstractName containerName = kernel.getAbstractNameFor(broker);
162            ProxyManager mgr = kernel.getProxyManager();
163            try {
164                List results = new ArrayList();
165                AbstractNameQuery query = new AbstractNameQuery(ActiveMQConnector.class.getName());
166                Set set = kernel.listGBeans(query); // all Jetty connectors
167                for (Iterator it = set.iterator(); it.hasNext();) {
168                    AbstractName name = (AbstractName) it.next(); // a single Jetty connector
169                    GBeanData data = kernel.getGBeanData(name);
170                    ReferencePatterns refs = data.getReferencePatterns("brokerService");
171                    if(containerName.equals(refs.getAbstractName())) {
172                        try {
173                            String testProtocol = (String) kernel.getAttribute(name, "protocol");
174                            if(testProtocol != null && testProtocol.equals(protocol)) {
175                                results.add(mgr.createProxy(name, ActiveMQConnector.class.getClassLoader()));
176                            }
177                        } catch (Exception e) {
178                            log.error("Unable to look up protocol for connector '"+name+"'",e);
179                        }
180                        break;
181                    }
182                }
183                return (ActiveMQConnector[]) results.toArray(new ActiveMQConnector[results.size()]);
184            } catch (Exception e) {
185                throw (IllegalArgumentException)new IllegalArgumentException("Unable to look up connectors for ActiveMQ broker '"+containerName +"': ").initCause(e);
186            }
187        }
188    
189        /**
190         * Returns a new JMSConnector.  Note that
191         * the connector may well require further customization before being fully
192         * functional (e.g. SSL settings for a secure connector).
193         */
194        public JMSConnector addConnector(JMSBroker broker, String uniqueName, String protocol, String host, int port) {
195            AbstractName brokerAbstractName = kernel.getAbstractNameFor(broker);
196            AbstractName name = kernel.getNaming().createChildName(brokerAbstractName, uniqueName, NameFactory.GERONIMO_SERVICE);
197            GBeanData connector = new GBeanData(name, TransportConnectorGBeanImpl.GBEAN_INFO);
198            //todo: if SSL is supported, need to add more properties or use a different GBean?
199            connector.setAttribute("protocol", protocol);
200            connector.setAttribute("host", host);
201            connector.setAttribute("port", new Integer(port));
202            connector.setReferencePattern("activeMQContainer", brokerAbstractName);
203            EditableConfigurationManager mgr = ConfigurationUtil.getEditableConfigurationManager(kernel);
204            if(mgr != null) {
205                try {
206                    mgr.addGBeanToConfiguration(brokerAbstractName.getArtifact(), connector, false);
207                    return (JMSConnector) kernel.getProxyManager().createProxy(name, ActiveMQConnector.class.getClassLoader());
208                } catch (InvalidConfigException e) {
209                    log.error("Unable to add GBean", e);
210                    return null;
211                } finally {
212                    ConfigurationUtil.releaseConfigurationManager(kernel, mgr);
213                }
214            } else {
215                log.warn("The ConfigurationManager in the kernel does not allow editing");
216                return null;
217            }
218        }
219    
220        public void removeConnector(AbstractName connectorName) {
221            try {
222                GBeanInfo info = kernel.getGBeanInfo(connectorName);
223                boolean found = false;
224                Set intfs = info.getInterfaces();
225                for (Iterator it = intfs.iterator(); it.hasNext();) {
226                    String intf = (String) it.next();
227                    if (intf.equals(ActiveMQConnector.class.getName())) {
228                        found = true;
229                    }
230                }
231                if (!found) {
232                    throw new GBeanNotFoundException(connectorName);
233                }
234                EditableConfigurationManager mgr = ConfigurationUtil.getEditableConfigurationManager(kernel);
235                if (mgr != null) {
236                    try {
237                        mgr.removeGBeanFromConfiguration(connectorName.getArtifact(), connectorName);
238                    } catch (InvalidConfigException e) {
239                        log.error("Unable to add GBean", e);
240                    } finally {
241                        ConfigurationUtil.releaseConfigurationManager(kernel, mgr);
242                    }
243                } else {
244                    log.warn("The ConfigurationManager in the kernel does not allow editing");
245                }
246            } catch (GBeanNotFoundException e) {
247                log.warn("No such GBean '" + connectorName + "'"); //todo: what if we want to remove a failed GBean?
248            } catch (Exception e) {
249                log.error(e);
250            }
251        }
252    
253        public static final GBeanInfo GBEAN_INFO;
254    
255        static {
256            GBeanInfoBuilder infoFactory = new GBeanInfoBuilder("ActiveMQ Manager", ActiveMQManagerGBean.class);
257            infoFactory.addAttribute("kernel", Kernel.class, false);
258            infoFactory.addAttribute("objectName", String.class, false);
259            infoFactory.addInterface(ActiveMQManager.class);
260            infoFactory.setConstructor(new String[]{"kernel", "objectName"});
261            GBEAN_INFO = infoFactory.getBeanInfo();
262        }
263    
264        public static GBeanInfo getGBeanInfo() {
265            return GBEAN_INFO;
266        }
267    }