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.framework;
018:
019: import java.io.File;
020: import java.io.IOException;
021: import java.util.Properties;
022:
023: import javax.jbi.JBIException;
024: import javax.jbi.component.Component;
025: import javax.jbi.component.ComponentLifeCycle;
026: import javax.jbi.component.ServiceUnitManager;
027: import javax.jbi.management.DeploymentException;
028: import javax.jbi.management.LifeCycleMBean;
029: import javax.management.JMException;
030: import javax.management.MBeanAttributeInfo;
031: import javax.management.MBeanOperationInfo;
032: import javax.management.ObjectName;
033:
034: import org.apache.commons.logging.Log;
035: import org.apache.commons.logging.LogFactory;
036: import org.apache.servicemix.jbi.container.ActivationSpec;
037: import org.apache.servicemix.jbi.container.JBIContainer;
038: import org.apache.servicemix.jbi.event.ComponentEvent;
039: import org.apache.servicemix.jbi.event.ComponentListener;
040: import org.apache.servicemix.jbi.management.AttributeInfoHelper;
041: import org.apache.servicemix.jbi.management.BaseLifeCycle;
042: import org.apache.servicemix.jbi.management.ManagementContext;
043: import org.apache.servicemix.jbi.management.OperationInfoHelper;
044: import org.apache.servicemix.jbi.messaging.DeliveryChannelImpl;
045: import org.apache.servicemix.jbi.util.XmlPersistenceSupport;
046: import org.apache.xbean.classloader.DestroyableClassLoader;
047:
048: /**
049: * Defines basic statistics on the Component
050: */
051: public class ComponentMBeanImpl extends BaseLifeCycle implements
052: ComponentMBean {
053:
054: private static final Log LOG = LogFactory
055: .getLog(ComponentMBeanImpl.class);
056:
057: private boolean exchangeThrottling;
058: private long throttlingTimeout = 100;
059: private int throttlingInterval = 1;
060: private Component component;
061: private ComponentLifeCycle lifeCycle;
062: private ServiceUnitManager suManager;
063: private ComponentContextImpl context;
064: private ActivationSpec activationSpec;
065: private ObjectName mBeanName;
066: private JBIContainer container;
067: private ComponentNameSpace componentName;
068: private String description = "POJO Component";
069: private int queueCapacity = 1024;
070: private boolean pojo;
071: private boolean binding;
072: private boolean service;
073: private File stateFile;
074: private String[] sharedLibraries;
075:
076: /**
077: * Construct with it's id and delivery channel Id
078: *
079: * @param name
080: * @param description
081: * @param component
082: * @param binding
083: * @param service
084: * @param sharedLibraries
085: */
086: public ComponentMBeanImpl(JBIContainer container,
087: ComponentNameSpace name, String description,
088: Component component, boolean binding, boolean service,
089: String[] sharedLibraries) {
090: this .componentName = name;
091: this .container = container;
092: this .component = component;
093: this .description = description;
094: this .binding = binding;
095: this .service = service;
096: this .sharedLibraries = sharedLibraries;
097: }
098:
099: public void dispose() {
100: ClassLoader cl = component.getClass().getClassLoader();
101: lifeCycle = null;
102: suManager = null;
103: component = null;
104: if (cl instanceof DestroyableClassLoader) {
105: ((DestroyableClassLoader) cl).destroy();
106: }
107: fireEvent(ComponentEvent.COMPONENT_UNINSTALLED);
108: }
109:
110: /**
111: * Register the MBeans for this Component
112: * @param ctx
113: * @return ObjectName
114: * @throws JBIException
115: */
116: public ObjectName registerMBeans(ManagementContext ctx)
117: throws JBIException {
118: try {
119: mBeanName = ctx.createObjectName(this );
120: ctx.registerMBean(mBeanName, this , ComponentMBean.class);
121: return mBeanName;
122: } catch (Exception e) {
123: String errorStr = "Failed to register MBeans";
124: LOG.error(errorStr, e);
125: throw new JBIException(errorStr, e);
126: }
127: }
128:
129: /**
130: * Unregister Component MBeans
131: * @param ctx
132: * @throws JBIException
133: */
134: public void unregisterMbeans(ManagementContext ctx)
135: throws JBIException {
136: ctx.unregisterMBean(mBeanName);
137: }
138:
139: /**
140: * Set the Context
141: *
142: * @param ctx
143: */
144: public void setContext(ComponentContextImpl ctx) {
145: this .context = ctx;
146: this .stateFile = ctx.getEnvironment().getStateFile();
147: }
148:
149: /**
150: * Get the JMX ObjectName for any additional MBean for this component. If there is none, return null.
151: *
152: * @return ObjectName the JMX object name of the additional MBean or null if there is no additional MBean.
153: */
154: public ObjectName getExtensionMBeanName() {
155: if (isInitialized() || isStarted() || isStopped()) {
156: return lifeCycle.getExtensionMBeanName();
157: } else {
158: return null;
159: }
160: }
161:
162: /**
163: * Get the name of the item
164: * @return the name
165: */
166: public String getName() {
167: return componentName.getName();
168: }
169:
170: /**
171: * Get the type of the item
172: * @return the type
173: */
174: public String getType() {
175: return "Component";
176: }
177:
178: public String getSubType() {
179: return "LifeCycle";
180: }
181:
182: /**
183: * Get the Description of the item
184: * @return the description
185: */
186: public String getDescription() {
187: return description;
188: }
189:
190: public void init() throws JBIException {
191: LOG.info("Initializing component: " + getName());
192: if (context != null && component != null) {
193: DeliveryChannelImpl channel = new DeliveryChannelImpl(this );
194: channel.setContext(context);
195: context.setDeliveryChannel(channel);
196: super .init();
197: fireEvent(ComponentEvent.COMPONENT_INITIALIZED);
198: ClassLoader loader = Thread.currentThread()
199: .getContextClassLoader();
200: try {
201: Thread.currentThread().setContextClassLoader(
202: getLifeCycle().getClass().getClassLoader());
203: getLifeCycle().init(context);
204: } finally {
205: Thread.currentThread().setContextClassLoader(loader);
206: }
207: }
208: }
209:
210: /**
211: * Start the item.
212: *
213: * @exception javax.jbi.JBIException if the item fails to start.
214: */
215: public void start() throws javax.jbi.JBIException {
216: LOG.info("Starting component: " + getName());
217: try {
218: doStart();
219: persistRunningState();
220: getContainer().getRegistry().checkPendingAssemblies();
221: } catch (JBIException e) {
222: LOG.error("Could not start component", e);
223: throw e;
224: } catch (RuntimeException e) {
225: LOG.error("Could not start component", e);
226: throw e;
227: } catch (Error e) {
228: LOG.error("Could not start component", e);
229: throw e;
230: }
231: }
232:
233: /**
234: * Stop the item. This suspends current messaging activities.
235: *
236: * @exception javax.jbi.JBIException if the item fails to stop.
237: */
238: public void stop() throws javax.jbi.JBIException {
239: LOG.info("Stopping component: " + getName());
240: try {
241: doStop();
242: persistRunningState();
243: } catch (JBIException e) {
244: LOG.error("Could not stop component", e);
245: throw e;
246: } catch (RuntimeException e) {
247: LOG.error("Could not start component", e);
248: throw e;
249: } catch (Error e) {
250: LOG.error("Could not start component", e);
251: throw e;
252: }
253: }
254:
255: /**
256: * Shut down the item. The releases resources, preparatory to uninstallation.
257: *
258: * @exception javax.jbi.JBIException if the item fails to shut down.
259: */
260: public void shutDown() throws javax.jbi.JBIException {
261: LOG.info("Shutting down component: " + getName());
262: try {
263: doShutDown();
264: persistRunningState();
265: } catch (JBIException e) {
266: LOG.error("Could not shutDown component", e);
267: throw e;
268: } catch (RuntimeException e) {
269: LOG.error("Could not start component", e);
270: throw e;
271: } catch (Error e) {
272: LOG.error("Could not start component", e);
273: throw e;
274: }
275: }
276:
277: public void setShutdownStateAfterInstall() {
278: setCurrentState(SHUTDOWN);
279: }
280:
281: /**
282: * Start the item - doesn't persist the state
283: *
284: * @exception javax.jbi.JBIException if the item fails to start.
285: */
286: public void doStart() throws javax.jbi.JBIException {
287: if (isShutDown()) {
288: // need to re-initialze before starting
289: init();
290: }
291: if (!isStarted()) {
292: ClassLoader loader = Thread.currentThread()
293: .getContextClassLoader();
294: try {
295: Thread.currentThread().setContextClassLoader(
296: getLifeCycle().getClass().getClassLoader());
297: getLifeCycle().start();
298: } finally {
299: Thread.currentThread().setContextClassLoader(loader);
300: }
301: super .start();
302: initServiceAssemblies();
303: startServiceAssemblies();
304: }
305: fireEvent(ComponentEvent.COMPONENT_STARTED);
306: }
307:
308: /**
309: * Stop the item - doesn't persist the state
310: *
311: * @exception javax.jbi.JBIException
312: * if the item fails to stop.
313: */
314: public void doStop() throws javax.jbi.JBIException {
315: if (isUnknown() || isStarted()) {
316: stopServiceAssemblies();
317: ClassLoader loader = Thread.currentThread()
318: .getContextClassLoader();
319: try {
320: Thread.currentThread().setContextClassLoader(
321: getLifeCycle().getClass().getClassLoader());
322: getLifeCycle().stop();
323: } finally {
324: Thread.currentThread().setContextClassLoader(loader);
325: }
326: super .stop();
327: }
328: fireEvent(ComponentEvent.COMPONENT_STOPPED);
329: }
330:
331: /**
332: * Shut down the item - doesn't persist the state
333: *
334: * @exception javax.jbi.JBIException if the item fails to shut down.
335: */
336: public void doShutDown() throws javax.jbi.JBIException {
337: // Transition from UNKNOWN to SHUTDOWN is done at installation time
338: // In this case or if the component is already shut down, do nothing
339: if (!isUnknown() && !isShutDown()) {
340: doStop();
341: shutDownServiceAssemblies();
342: ClassLoader loader = Thread.currentThread()
343: .getContextClassLoader();
344: try {
345: Thread.currentThread().setContextClassLoader(
346: getLifeCycle().getClass().getClassLoader());
347: getLifeCycle().shutDown();
348: } finally {
349: Thread.currentThread().setContextClassLoader(loader);
350: }
351: if (getDeliveryChannel() != null) {
352: getDeliveryChannel().close();
353: setDeliveryChannel(null);
354: }
355: lifeCycle = null;
356: suManager = null;
357: }
358: super .shutDown();
359: fireEvent(ComponentEvent.COMPONENT_SHUTDOWN);
360: }
361:
362: /**
363: * Set the initial running state of the Component
364: * @throws JBIException
365: */
366: public void setInitialRunningState() throws JBIException {
367: if (!isPojo()) {
368: String name = getName();
369: String runningState = getRunningStateFromStore();
370: LOG.info("Setting running state for Component: " + name
371: + " to " + runningState);
372: if (runningState != null) {
373: if (runningState.equals(LifeCycleMBean.STARTED)) {
374: doStart();
375: } else if (runningState.equals(LifeCycleMBean.STOPPED)) {
376: doStart();
377: doStop();
378: } else if (runningState.equals(LifeCycleMBean.SHUTDOWN)) {
379: doShutDown();
380: }
381: }
382: }
383: }
384:
385: /**
386: * Persist the running state
387: */
388: public void persistRunningState() {
389: if (!isPojo()) {
390: String name = getName();
391: try {
392: String currentState = getCurrentState();
393: Properties props = new Properties();
394: props.setProperty("state", currentState);
395: XmlPersistenceSupport.write(stateFile, props);
396: } catch (IOException e) {
397: LOG.error(
398: "Failed to write current running state for Component: "
399: + name, e);
400: }
401: }
402: }
403:
404: /**
405: * @return the current running state from disk
406: */
407: public String getRunningStateFromStore() {
408: String result = LifeCycleMBean.UNKNOWN;
409: String name = getName();
410: try {
411: Properties props = (Properties) XmlPersistenceSupport
412: .read(stateFile);
413: result = props.getProperty("state", result);
414: } catch (Exception e) {
415: LOG.error("Failed to read running state for Component: "
416: + name, e);
417: }
418: return result;
419: }
420:
421: /**
422: * @return the capacity of the inbound queue
423: */
424: public int getInboundQueueCapacity() {
425: return queueCapacity;
426: }
427:
428: /**
429: * Set the inbound queue capacity
430: * @param value
431: */
432: public void setInboundQueueCapacity(int value) {
433: if (getDeliveryChannel() != null) {
434: throw new IllegalStateException(
435: "The component must be shut down before changing queue capacity");
436: }
437: this .queueCapacity = value;
438: }
439:
440: /**
441: * @return Returns the deliveryChannel.
442: */
443: public DeliveryChannelImpl getDeliveryChannel() {
444: return (DeliveryChannelImpl) context.getDeliveryChannel();
445: }
446:
447: /**
448: * @param deliveryChannel
449: * The deliveryChannel to set.
450: */
451: public void setDeliveryChannel(DeliveryChannelImpl deliveryChannel) {
452: context.setDeliveryChannel(deliveryChannel);
453: }
454:
455: /**
456: * @return the ActivateionSpec
457: */
458: public ActivationSpec getActivationSpec() {
459: return activationSpec;
460: }
461:
462: /**
463: * @return Returns the pojo.
464: */
465: public boolean isPojo() {
466: return pojo;
467: }
468:
469: /**
470: * Set the ActivationSpec
471: *
472: * @param activationSpec
473: */
474: public void setActivationSpec(ActivationSpec activationSpec) {
475: this .activationSpec = activationSpec;
476: }
477:
478: /**
479: * Is MessageExchange sender throttling enabled ?
480: *
481: * @return true if throttling enabled
482: */
483: public boolean isExchangeThrottling() {
484: return exchangeThrottling;
485: }
486:
487: /**
488: * Set message throttling
489: *
490: * @param value
491: */
492: public void setExchangeThrottling(boolean value) {
493: this .exchangeThrottling = value;
494: }
495:
496: /**
497: * Get the throttling timeout
498: *
499: * @return throttling tomeout (ms)
500: */
501: public long getThrottlingTimeout() {
502: return throttlingTimeout;
503: }
504:
505: /**
506: * Set the throttling timout
507: *
508: * @param value (ms)
509: */
510: public void setThrottlingTimeout(long value) {
511: throttlingTimeout = value;
512: }
513:
514: /**
515: * Get the interval for throttling - number of Exchanges set before the throttling timeout is applied
516: *
517: * @return interval for throttling
518: */
519: public int getThrottlingInterval() {
520: return throttlingInterval;
521: }
522:
523: /**
524: * Set the throttling interval number of Exchanges set before the throttling timeout is applied
525: *
526: * @param value
527: */
528: public void setThrottlingInterval(int value) {
529: throttlingInterval = value;
530: }
531:
532: /**
533: * Get an array of MBeanAttributeInfo
534: *
535: * @return array of AttributeInfos
536: * @throws JMException
537: */
538: public MBeanAttributeInfo[] getAttributeInfos() throws JMException {
539: AttributeInfoHelper helper = new AttributeInfoHelper();
540: helper.addAttribute(getObjectToManage(), "componentType",
541: "the type of this component (BC, SE, POJO)");
542: helper
543: .addAttribute(getObjectToManage(),
544: "inboundQueueCapacity",
545: "capacity of the inbound queue");
546: helper.addAttribute(getObjectToManage(), "exchangeThrottling",
547: "apply throttling");
548: helper.addAttribute(getObjectToManage(), "throttlingTimeout",
549: "timeout for throttling");
550: helper.addAttribute(getObjectToManage(), "throttlingInterval",
551: "exchange intervals before throttling");
552: helper.addAttribute(getObjectToManage(), "extensionMBeanName",
553: "extension mbean name");
554: return AttributeInfoHelper.join(super .getAttributeInfos(),
555: helper.getAttributeInfos());
556: }
557:
558: /**
559: * Get an array of MBeanOperationInfo
560: *
561: * @return array of OperationInfos
562: * @throws JMException
563: */
564: public MBeanOperationInfo[] getOperationInfos() throws JMException {
565: OperationInfoHelper helper = new OperationInfoHelper();
566: return OperationInfoHelper.join(super .getOperationInfos(),
567: helper.getOperationInfos());
568: }
569:
570: public void firePropertyChanged(String name, Object oldValue,
571: Object newValue) {
572: super .firePropertyChanged(name, oldValue, newValue);
573: }
574:
575: protected void initServiceAssemblies() throws DeploymentException {
576: }
577:
578: protected void startServiceAssemblies() throws DeploymentException {
579: }
580:
581: protected void stopServiceAssemblies() throws DeploymentException {
582: Registry registry = getContainer().getRegistry();
583: String[] sas = registry
584: .getDeployedServiceAssembliesForComponent(getName());
585: for (int i = 0; i < sas.length; i++) {
586: ServiceAssemblyLifeCycle sa = registry
587: .getServiceAssembly(sas[i]);
588: if (sa.isStarted()) {
589: try {
590: sa.stop(false, false);
591: registry.addPendingAssembly(sa);
592: } catch (Exception e) {
593: LOG.error("Error stopping service assembly "
594: + sas[i]);
595: }
596: }
597: }
598: }
599:
600: protected void shutDownServiceAssemblies()
601: throws DeploymentException {
602: Registry registry = getContainer().getRegistry();
603: String[] sas = registry
604: .getDeployedServiceAssembliesForComponent(getName());
605: for (int i = 0; i < sas.length; i++) {
606: ServiceAssemblyLifeCycle sa = registry
607: .getServiceAssembly(sas[i]);
608: if (sa.isStopped()) {
609: try {
610: sa.shutDown(false);
611: registry.addPendingAssembly(sa);
612: } catch (Exception e) {
613: LOG.error("Error shutting down service assembly "
614: + sas[i]);
615: }
616: }
617: }
618: }
619:
620: protected void fireEvent(int type) {
621: ComponentEvent event = new ComponentEvent(this , type);
622: ComponentListener[] listeners = (ComponentListener[]) getContainer()
623: .getListeners(ComponentListener.class);
624: for (int i = 0; i < listeners.length; i++) {
625: switch (type) {
626: case ComponentEvent.COMPONENT_INITIALIZED:
627: listeners[i].componentInitialized(event);
628: break;
629: case ComponentEvent.COMPONENT_STARTED:
630: listeners[i].componentStarted(event);
631: break;
632: case ComponentEvent.COMPONENT_STOPPED:
633: listeners[i].componentStopped(event);
634: break;
635: case ComponentEvent.COMPONENT_SHUTDOWN:
636: listeners[i].componentShutDown(event);
637: break;
638: case ComponentEvent.COMPONENT_UNINSTALLED:
639: listeners[i].componentUninstalled(event);
640: break;
641: default:
642: break;
643: }
644: }
645:
646: }
647:
648: public ComponentLifeCycle getLifeCycle() {
649: if (lifeCycle == null) {
650: lifeCycle = component.getLifeCycle();
651: }
652: return lifeCycle;
653: }
654:
655: public ServiceUnitManager getServiceUnitManager() {
656: if (suManager == null) {
657: suManager = component.getServiceUnitManager();
658: }
659: return suManager;
660: }
661:
662: public JBIContainer getContainer() {
663: return container;
664: }
665:
666: public Component getComponent() {
667: return component;
668: }
669:
670: public ComponentNameSpace getComponentNameSpace() {
671: return componentName;
672: }
673:
674: public ComponentContextImpl getContext() {
675: return context;
676: }
677:
678: public ObjectName getMBeanName() {
679: return mBeanName;
680: }
681:
682: public boolean isBinding() {
683: return binding;
684: }
685:
686: public boolean isService() {
687: return service;
688: }
689:
690: public void setPojo(boolean pojo) {
691: this .pojo = pojo;
692: }
693:
694: public boolean isEngine() {
695: return service;
696: }
697:
698: /**
699: * @return the sharedLibraries
700: */
701: public String[] getSharedLibraries() {
702: return sharedLibraries;
703: }
704:
705: /**
706: * @return the component type
707: */
708: public String getComponentType() {
709: return isBinding() ? "binding-component"
710: : isEngine() ? "service-engine" : "pojo";
711: }
712:
713: }
|