001: /*
002: * JBoss, Home of Professional Open Source.
003: * Copyright 2006, Red Hat Middleware LLC, and individual contributors
004: * as indicated by the @author tags. See the copyright.txt file in the
005: * distribution for a full listing of individual contributors.
006: *
007: * This is free software; you can redistribute it and/or modify it
008: * under the terms of the GNU Lesser General Public License as
009: * published by the Free Software Foundation; either version 2.1 of
010: * the License, or (at your option) any later version.
011: *
012: * This software is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: *
017: * You should have received a copy of the GNU Lesser General Public
018: * License along with this software; if not, write to the Free
019: * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
021: */
022: package org.jboss.services.binding;
023:
024: import java.net.URL;
025:
026: import javax.management.Attribute;
027: import javax.management.MBeanRegistration;
028: import javax.management.MBeanServer;
029: import javax.management.ObjectName;
030:
031: import org.jboss.logging.Logger;
032: import org.jboss.mx.util.JMXExceptionDecoder;
033: import org.jboss.mx.util.MBeanProxyExt;
034: import org.jboss.system.ServiceControllerMBean;
035: import org.jboss.system.server.ServerConfigLocator;
036:
037: /** The services configuration binding manager mbean implementation.
038: *
039: * <p>The ServiceBindingManager enables the centralized management
040: * of ports, by service. The port configuration store is abstracted out
041: * using the ServicesStore and ServicesStoreFactory interfaces. Note that
042: * this class does not implement the JBoss services lifecycle methods
043: * and hook its behavior off of those because this service is used to
044: * configure other services before any of the lifecycle methods are invoked.
045: *
046: * @version $Revision: 57210 $
047: * @author <a href="mailto:bitpushr@rochester.rr.com">Mike Finn</a>
048: * @author Scott.Stark@jboss.org
049: * @author <a href="mailto:dimitris@jboss.org">Dimitris Andreadis</a>
050: *
051: * @jmx:mbean
052: */
053: public class ServiceBindingManager implements MBeanRegistration,
054: ServiceBindingManagerMBean {
055: private static Logger log = Logger
056: .getLogger(ServiceBindingManager.class);
057:
058: /** The MBeanServer we are registered
059: */
060: private MBeanServer server;
061:
062: /** The ObjectName of this MBean
063: */
064: private ObjectName serviceName;
065:
066: /** The name of the server this manager is associated with. This is a
067: logical name used to lookup ServiceConfigs from the ServicesStore.
068: */
069: private String serverName;
070:
071: /** The name of the class implementation for the ServicesStoreFactory. The
072: default value is org.jboss.services.binding.XMLServicesStoreFactory
073: */
074: private String storeFactoryClassName = "org.jboss.services.binding.XMLServicesStoreFactory";
075:
076: /** The ObjectName of the ServiceController we'll be registering at
077: */
078: private ObjectName serviceController;
079:
080: /** The ServiceConfig store instance
081: */
082: private ServicesStore store;
083:
084: /** The URL of the configuration store
085: */
086: private URL storeURL;
087:
088: // Attributes ----------------------------------------------------
089:
090: /**
091: * @jmx:managed-attribute
092: */
093: public String getServerName() {
094: return this .serverName;
095: }
096:
097: /**
098: * @jmx:managed-attribute
099: */
100: public void setServerName(String serverName) {
101: this .serverName = serverName;
102: }
103:
104: /**
105: * @jmx:managed-attribute
106: */
107: public String getStoreFactoryClassName() {
108: return this .storeFactoryClassName;
109: }
110:
111: /**
112: * @jmx:managed-attribute
113: */
114: public void setStoreFactoryClassName(String storeFactoryClassName) {
115: this .storeFactoryClassName = storeFactoryClassName;
116: }
117:
118: /**
119: * @jmx:managed-attribute
120: */
121: public URL getStoreURL() {
122: return storeURL;
123: }
124:
125: /** Set the string representation of the store URL
126: * @jmx:managed-attribute
127: */
128: public void setStoreURL(URL storeURL) {
129: this .storeURL = storeURL;
130: }
131:
132: /**
133: * Get the ObjectName of the ServiceController
134: * @jmx:managed-attribute
135: */
136: public ObjectName getServiceController() {
137: return serviceController;
138: }
139:
140: /**
141: * Set the ObjectName of the ServiceController.
142: *
143: * @jmx:managed-attribute
144: *
145: * @param serviceController the name of the controller to register to
146: * @throws Exception if there is a problem registering with the controller
147: */
148: public void setServiceController(ObjectName serviceController)
149: throws Exception {
150: this .serviceController = serviceController;
151:
152: // try to register a proxy with the controller
153: registerProxy();
154: }
155:
156: // MBeanRegistration overrides -----------------------------------
157:
158: public ObjectName preRegister(MBeanServer server, ObjectName name)
159: throws Exception {
160: this .server = server;
161: this .serviceName = name;
162:
163: return name;
164: }
165:
166: public void postRegister(Boolean registrationDone) {
167: if (registrationDone.booleanValue()) {
168: // Register with the default ServiceController
169: try {
170: setServiceController(ServiceControllerMBean.OBJECT_NAME);
171: } catch (Exception ignore) {
172: // Ignore any exception at this point; the user
173: // might expicitly set the controller objectname
174: }
175: }
176: }
177:
178: public void preDeregister() throws Exception {
179: // unregister with ServiceController
180: this .unregisterProxy();
181:
182: // shutdown store
183: if (store != null) {
184: store.store(storeURL);
185: }
186: }
187:
188: public void postDeregister() {
189: // empty
190: }
191:
192: // Operations ----------------------------------------------------
193:
194: /**
195: * Looks up the service config for the given service using the
196: * server name bound to this mbean.
197: *
198: * @jmx:managed-operation
199: *
200: * @param serviceName the JMX ObjectName of the service
201: * @return ServiceConfig instance if found, null otherwise
202: */
203: public ServiceConfig getServiceConfig(ObjectName serviceName)
204: throws Exception {
205: log.debug("getServiceConfig, server:" + serverName
206: + ", serviceName:" + serviceName);
207:
208: if (store == null) {
209: initStore();
210: }
211:
212: // Look up the service config
213: ServiceConfig svcConfig = store.getService(serverName,
214: serviceName);
215: ServiceConfig configCopy = null;
216: if (svcConfig != null) {
217: configCopy = (ServiceConfig) svcConfig.clone();
218: }
219: return configCopy;
220: }
221:
222: /**
223: * Looks up the service config for the requested service using the
224: * server name bound to this mbean and invokes the configuration delegate
225: * to apply the bindings to the service. If no config if found then this
226: * method is a noop.
227: *
228: * @jmx:managed-operation
229: *
230: * @param serviceName the JMX ObjectName of the service
231: * @exception Exception, thrown on failure to apply an existing configuration
232: */
233: public void applyServiceConfig(ObjectName serviceName)
234: throws Exception {
235: if (store == null) {
236: initStore();
237: }
238: // Look up the service config
239: ServiceConfig svcConfig = store.getService(serverName,
240: serviceName);
241: if (svcConfig != null) {
242: log.debug("applyServiceConfig, server:" + serverName
243: + ", serviceName:" + serviceName + ", config="
244: + svcConfig);
245:
246: ClassLoader loader = Thread.currentThread()
247: .getContextClassLoader();
248: String delegateName = svcConfig
249: .getServiceConfigDelegateClassName();
250: if (delegateName != null) {
251: Class delegateClass = loader.loadClass(delegateName);
252: ServicesConfigDelegate delegate = (ServicesConfigDelegate) delegateClass
253: .newInstance();
254: delegate.applyConfig(svcConfig, server);
255: }
256: }
257: }
258:
259: // Private -------------------------------------------------------
260:
261: /**
262: * Register a dynamic proxy of myself with the ServiceController
263: */
264: private void registerProxy() throws Exception {
265: if (serviceController != null) {
266: log.debug("Registering with ServiceController: "
267: + serviceController);
268:
269: // Create a dynamic proxy pointing to me, over the MBeanServer
270: org.jboss.system.ServiceBinding proxy = (org.jboss.system.ServiceBinding) MBeanProxyExt
271: .create(org.jboss.system.ServiceBinding.class,
272: serviceName, server);
273:
274: try {
275: server.setAttribute(serviceController, new Attribute(
276: "ServiceBinding", proxy));
277: } catch (Exception e) {
278: // Log a debug message indicating we couldn't register and rethrow
279: Throwable t = JMXExceptionDecoder.decode(e);
280: log.debug("Failed to register with ServiceController: "
281: + serviceController + ", reason: "
282: + t.getMessage());
283: throw (Exception) t;
284: }
285: }
286: }
287:
288: /**
289: * Unregister with ServiceController
290: * by setting ServiceBinding to null
291: */
292: private void unregisterProxy() {
293: if (serviceController != null) {
294: log.debug("Unregistering with ServiceController: "
295: + serviceController);
296: try {
297: server.setAttribute(serviceController, new Attribute(
298: "ServiceBinding", null));
299: } catch (Exception e) {
300: // Log a debug message indicating we couldn't unregister
301: Throwable t = JMXExceptionDecoder.decode(e);
302: log
303: .debug("Failed to unregister with ServiceController: "
304: + serviceController
305: + ", reason: "
306: + t.getMessage());
307: }
308: }
309: }
310:
311: /**
312: * Create and load the services store
313: */
314: private void initStore() throws Exception {
315: log.info("Initializing store");
316:
317: // If no store url identified, use the ServerConfigURL
318: if (this .storeURL == null) {
319: this .storeURL = ServerConfigLocator.locate()
320: .getServerConfigURL();
321: }
322: log.info("Using StoreURL: " + storeURL);
323:
324: ClassLoader loader = Thread.currentThread()
325: .getContextClassLoader();
326: Class factoryClass = loader.loadClass(storeFactoryClassName);
327: ServicesStoreFactory storeFactory = (ServicesStoreFactory) factoryClass
328: .newInstance();
329:
330: // Create and load the store
331: store = storeFactory.newInstance();
332: store.load(storeURL);
333: }
334: }
|