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.jbi.jmx;
018
019 import java.util.Map;
020
021 import javax.management.MBeanServer;
022 import javax.management.MalformedObjectNameException;
023
024 import org.apache.commons.logging.Log;
025 import org.apache.commons.logging.LogFactory;
026 import org.springframework.beans.factory.DisposableBean;
027 import org.springframework.beans.factory.FactoryBean;
028 import org.springframework.beans.factory.InitializingBean;
029 import org.springframework.core.Constants;
030
031 /**
032 * <code>FactoryBean</code> that creates a JSR-160 <code>JMXConnectorServer</code>,
033 * optionally registers it with the <code>MBeanServer</code> and then starts it.
034 *
035 * <p>The <code>JMXConnectorServer</code> can be started in a separate thread by setting the
036 * <code>threaded</code> property to <code>true</code>. You can configure this thread to be a
037 * daemon thread by setting the <code>daemon</code> property to <code>true</code>.
038 *
039 * This xbean-enabled factory is a wrapper on top of the existing Spring
040 * factory bean. It also logs the serviceUrl when starting.
041 *
042 * @author gnodet
043 * @org.apache.xbean.XBean element="jmxConnector"
044 */
045 public class ConnectorServerFactoryBean implements FactoryBean, InitializingBean, DisposableBean {
046
047 /**
048 * Constant indicating that registration should fail when
049 * attempting to register an MBean under a name that already exists.
050 * <p>This is the default registration behavior.
051 */
052 public static final int REGISTRATION_FAIL_ON_EXISTING = 0;
053
054 /**
055 * Constant indicating that registration should ignore the affected MBean
056 * when attempting to register an MBean under a name that already exists.
057 */
058 public static final int REGISTRATION_IGNORE_EXISTING = 1;
059
060 /**
061 * Constant indicating that registration should replace the affected MBean
062 * when attempting to register an MBean under a name that already exists.
063 */
064 public static final int REGISTRATION_REPLACE_EXISTING = 2;
065
066 private static final Constants CONSTANTS = new Constants(ConnectorServerFactoryBean.class);
067
068 private Log log = LogFactory.getLog(ConnectorServerFactoryBean.class);
069 private org.springframework.jmx.support.ConnectorServerFactoryBean csfb =
070 new org.springframework.jmx.support.ConnectorServerFactoryBean();
071 private String serviceUrl = org.springframework.jmx.support.ConnectorServerFactoryBean.DEFAULT_SERVICE_URL;
072 private boolean daemon;
073 private boolean threaded;
074 private Map environment;
075 private Object objectName;
076 private int registrationBehavior = REGISTRATION_FAIL_ON_EXISTING;
077 private MBeanServer server;
078
079
080 /**
081 * Set whether any threads started for the <code>JMXConnectorServer</code> should be
082 * started as daemon threads.
083 * @param daemon
084 * @see org.springframework.jmx.support.ConnectorServerFactoryBean#setDaemon(boolean)
085 */
086 public void setDaemon(boolean daemon) {
087 this.daemon = daemon;
088 }
089
090 /**
091 * Set the environment properties used to construct the <code>JMXConnector</code>
092 * as a <code>Map</code> of String keys and arbitrary Object values.
093 * @param environment
094 * @see org.springframework.jmx.support.ConnectorServerFactoryBean#setEnvironmentMap(java.util.Map)
095 */
096 public void setEnvironment(Map environment) {
097 this.environment = environment;
098 }
099
100 /**
101 * Set the <code>ObjectName</code> used to register the <code>JMXConnectorServer</code>
102 * itself with the <code>MBeanServer</code>.
103 * @param objectName
104 * @throws MalformedObjectNameException if the <code>ObjectName</code> is malformed
105 * @see org.springframework.jmx.support.ConnectorServerFactoryBean#setObjectName(java.lang.String)
106 */
107 public void setObjectName(String objectName) throws MalformedObjectNameException {
108 this.objectName = objectName;
109 }
110
111 /**
112 * Specify what action should be taken when attempting to register an MBean
113 * under an {@link javax.management.ObjectName} that already exists.
114 * <p>Default is REGISTRATION_FAIL_ON_EXISTING.
115 * @see #setRegistrationBehaviorName(String)
116 * @see #REGISTRATION_FAIL_ON_EXISTING
117 * @see #REGISTRATION_IGNORE_EXISTING
118 * @see #REGISTRATION_REPLACE_EXISTING
119 * @param registrationBehavior
120 * @see org.springframework.jmx.support.MBeanRegistrationSupport#setRegistrationBehavior(int)
121 */
122 public void setRegistrationBehavior(int registrationBehavior) {
123 this.registrationBehavior = registrationBehavior;
124 }
125
126 /**
127 * Set the registration behavior by the name of the corresponding constant,
128 * e.g. "REGISTRATION_IGNORE_EXISTING".
129 * @see #setRegistrationBehavior
130 * @see #REGISTRATION_FAIL_ON_EXISTING
131 * @see #REGISTRATION_IGNORE_EXISTING
132 * @see #REGISTRATION_REPLACE_EXISTING
133 * @param behavior
134 * @see org.springframework.jmx.support.MBeanRegistrationSupport#setRegistrationBehaviorName(java.lang.String)
135 */
136 public void setRegistrationBehaviorName(String behavior) {
137 setRegistrationBehavior(CONSTANTS.asNumber(behavior).intValue());
138 }
139
140 /**
141 * Specify the <code>MBeanServer</code> instance with which all beans should
142 * be registered. The <code>MBeanExporter</code> will attempt to locate an
143 * existing <code>MBeanServer</code> if none is supplied.
144 * @param server
145 * @see org.springframework.jmx.support.MBeanRegistrationSupport#setServer(javax.management.MBeanServer)
146 */
147 public void setServer(MBeanServer server) {
148 this.server = server;
149 }
150
151 /**
152 * Set the service URL for the <code>JMXConnectorServer</code>.
153 * @param serviceUrl
154 * @see org.springframework.jmx.support.ConnectorServerFactoryBean#setServiceUrl(java.lang.String)
155 */
156 public void setServiceUrl(String serviceUrl) {
157 this.serviceUrl = serviceUrl;
158 }
159
160 /**
161 * Set whether the <code>JMXConnectorServer</code> should be started in a separate thread.
162 * @param threaded
163 * @see org.springframework.jmx.support.ConnectorServerFactoryBean#setThreaded(boolean)
164 */
165 public void setThreaded(boolean threaded) {
166 csfb.setThreaded(threaded);
167 }
168
169 public Object getObject() throws Exception {
170 return csfb.getObject();
171 }
172
173 public Class getObjectType() {
174 return csfb.getObjectType();
175 }
176
177 public boolean isSingleton() {
178 return csfb.isSingleton();
179 }
180
181 public void afterPropertiesSet() throws Exception {
182 csfb = new org.springframework.jmx.support.ConnectorServerFactoryBean();
183 csfb.setDaemon(daemon);
184 csfb.setThreaded(threaded);
185 csfb.setRegistrationBehavior(registrationBehavior);
186 csfb.setEnvironmentMap(environment);
187 csfb.setObjectName(objectName);
188 serviceUrl = serviceUrl.replaceAll(" ", "");
189 csfb.setServiceUrl(serviceUrl);
190 csfb.setServer(server);
191 csfb.afterPropertiesSet();
192 log.info("JMX connector available at: " + serviceUrl);
193 }
194
195 public void destroy() throws Exception {
196 if (csfb != null) {
197 try {
198 csfb.destroy();
199 } finally {
200 csfb = null;
201 }
202 }
203 }
204
205 }