001 /*****************************************************************************
002 * Copyright (C) PicoContainer Organization. All rights reserved. *
003 * ------------------------------------------------------------------------- *
004 * The software in this package is published under the terms of the BSD *
005 * style license a copy of which has been included with this distribution in *
006 * the LICENSE.txt file. *
007 *****************************************************************************/
008 package org.picocontainer.lifecycle;
009
010 import org.picocontainer.ComponentMonitor;
011 import org.picocontainer.Disposable;
012 import org.picocontainer.Startable;
013
014 import java.lang.reflect.Method;
015
016 /**
017 * Startable lifecycle strategy. Starts and stops component if Startable,
018 * and disposes it if Disposable.
019 *
020 * A subclass of this class can define other intrfaces for Startable/Disposable as well as other method names
021 * for start/stop/dispose
022 *
023 * @author Mauro Talevi
024 * @author Jörg Schaible
025 * @see Startable
026 * @see Disposable
027 */
028 public class StartableLifecycleStrategy extends AbstractMonitoringLifecycleStrategy {
029
030 private transient Method start, stop, dispose;
031
032 public StartableLifecycleStrategy(ComponentMonitor monitor) {
033 super(monitor);
034 }
035
036 private void doMethodsIfNotDone() {
037 try {
038 if (start == null) {
039 start = getStartableInterface().getMethod(getStartMethodName());
040 }
041 if (stop == null) {
042 stop = getStartableInterface().getMethod(getStopMethodName());
043 }
044 if (dispose == null) {
045 dispose = getDisposableInterface().getMethod(getDisposeMethodName());
046 }
047 } catch (NoSuchMethodException e) {
048 }
049 }
050
051 protected String getDisposeMethodName() {
052 return "dispose";
053 }
054
055 protected String getStopMethodName() {
056 return "stop";
057 }
058
059 protected String getStartMethodName() {
060 return "start";
061 }
062
063
064 public void start(Object component) {
065 doMethodsIfNotDone();
066 if (component != null && getStartableInterface().isAssignableFrom(component.getClass())) {
067 long str = System.currentTimeMillis();
068 currentMonitor().invoking(null, null, start, component);
069 try {
070 startComponent(component);
071 currentMonitor().invoked(null, null, start, component, System.currentTimeMillis() - str);
072 } catch (RuntimeException cause) {
073 currentMonitor().lifecycleInvocationFailed(null, null, start, component, cause); // may re-throw
074 }
075 }
076 }
077
078 protected void startComponent(Object component) {
079 ((Startable) component).start();
080 }
081 protected void stopComponent(Object component) {
082 ((Startable) component).stop();
083 }
084 protected void disposeComponent(Object component) {
085 ((Disposable) component).dispose();
086 }
087
088 public void stop(Object component) {
089 doMethodsIfNotDone();
090 if (component != null && getStartableInterface().isAssignableFrom(component.getClass())) {
091 long str = System.currentTimeMillis();
092 currentMonitor().invoking(null, null, stop, component);
093 try {
094 stopComponent(component);
095 currentMonitor().invoked(null, null, stop, component, System.currentTimeMillis() - str);
096 } catch (RuntimeException cause) {
097 currentMonitor().lifecycleInvocationFailed(null, null, stop, component, cause); // may re-throw
098 }
099 }
100 }
101
102 public void dispose(Object component) {
103 doMethodsIfNotDone();
104 if (component != null && getDisposableInterface().isAssignableFrom(component.getClass())) {
105 long str = System.currentTimeMillis();
106 currentMonitor().invoking(null, null, dispose, component);
107 try {
108 disposeComponent(component);
109 currentMonitor().invoked(null, null, dispose, component, System.currentTimeMillis() - str);
110 } catch (RuntimeException cause) {
111 currentMonitor().lifecycleInvocationFailed(null, null, dispose, component, cause); // may re-throw
112 }
113 }
114 }
115
116 public boolean hasLifecycle(Class type) {
117 return getStartableInterface().isAssignableFrom(type) || getDisposableInterface().isAssignableFrom(type);
118 }
119
120 protected Class<Disposable> getDisposableInterface() {
121 return Disposable.class;
122 }
123
124 protected Class getStartableInterface() {
125 return Startable.class;
126 }
127 }