Source Code Cross Referenced for DefaultLifecycleInterceptor.java in  » Inversion-of-Control » carbon » org » sape » carbon » core » component » lifecycle » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Inversion of Control » carbon » org.sape.carbon.core.component.lifecycle 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * The contents of this file are subject to the Sapient Public License
0003:         * Version 1.0 (the "License"); you may not use this file except in compliance
0004:         * with the License. You may obtain a copy of the License at
0005:         * http://carbon.sf.net/License.html.
0006:         *
0007:         * Software distributed under the License is distributed on an "AS IS" basis,
0008:         * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
0009:         * the specific language governing rights and limitations under the License.
0010:         *
0011:         * The Original Code is The Carbon Component Framework.
0012:         *
0013:         * The Initial Developer of the Original Code is Sapient Corporation
0014:         *
0015:         * Copyright (C) 2003 Sapient Corporation. All Rights Reserved.
0016:         */
0017:
0018:        package org.sape.carbon.core.component.lifecycle;
0019:
0020:        import java.util.Collections;
0021:        import java.util.HashSet;
0022:        import java.util.Set;
0023:        import java.lang.reflect.Proxy;
0024:        import java.lang.reflect.InvocationHandler;
0025:        import java.lang.reflect.Method;
0026:
0027:        import org.sape.carbon.core.component.Component;
0028:        import org.sape.carbon.core.component.ComponentConfiguration;
0029:        import org.sape.carbon.core.component.FunctionalInterface;
0030:        import org.sape.carbon.core.component.event.ComponentEvent;
0031:        import org.sape.carbon.core.component.event.EventManager;
0032:        import org.sape.carbon.core.component.proxy.ComponentProxyInvocationHandler;
0033:        import org.sape.carbon.core.component.proxy.Interceptor;
0034:        import org.sape.carbon.core.component.proxy.Invocation;
0035:        import org.sape.carbon.core.component.proxy.MonitorAcquisitionException;
0036:        import org.sape.carbon.core.component.proxy.AbstractInterceptor;
0037:        import org.sape.carbon.core.exception.ExceptionUtility;
0038:
0039:        import org.apache.commons.logging.Log;
0040:        import org.apache.commons.logging.LogFactory;
0041:
0042:        /**
0043:         * This is the default implementation of the lifecycle interceptor interface.
0044:         * This class takes on the responsibility of delegating
0045:         *
0046:         * Copyright 2002 Sapient
0047:         * @since carbon 1.0
0048:         * @author Chris Herron, January 2002
0049:         * @version $Revision: 1.9 $($Author: ghinkl $ / $Date: 2003/10/15 21:40:19 $)
0050:         */
0051:        public class DefaultLifecycleInterceptor extends AbstractInterceptor
0052:                implements  LifecycleInterceptor, Interceptor {
0053:
0054:            /** Array of interfaces this proxy adds to a component. */
0055:            protected static final Class[] EXPOSED_INTERFACES = new Class[] { LifecycleInterceptor.class };
0056:
0057:            /** Provides handle to Apache-commons logger. */
0058:            private Log log = LogFactory.getLog(this .getClass());
0059:
0060:            /** Name of lifecycle change event. */
0061:            public static final String LIFECYCLE_CHANGE_EVENT_NAME = "Component.LifecycleChange";
0062:
0063:            /**
0064:             * This method must implement the invocation of any necessary actions and
0065:             * the chaining the next interceptor.
0066:             * @param invocation the invocation to execute
0067:             * @return the results of the invocation's execution
0068:             *
0069:             * @throws Throwable indicates an error in the invocation chain
0070:             */
0071:            public Object invoke(Invocation invocation) throws Throwable {
0072:
0073:                if (invocation.isTargetFunctionalImplementation()) {
0074:                    // If the target is the component's implementation and we're
0075:                    // not it a running state, try and wait until we're ready to go
0076:                    LifecycleStateEnum state = getLifecycleState();
0077:
0078:                    if (state != LifecycleStateEnum.RUNNING) {
0079:                        if (state == LifecycleStateEnum.SUSPENDED
0080:                                || state == LifecycleStateEnum.RESUMING) {
0081:
0082:                            waitForResume();
0083:                        } else {
0084:                            throw new ComponentUnavailableException(
0085:                                    this .getClass(),
0086:                                    "The component is not in a LifecycleStateEnum.RUNNING "
0087:                                            + "state, FunctionalInterface methods "
0088:                                            + "cannot be called. "
0089:                                            + "Component name ["
0090:                                            + getComponentName()
0091:                                            + "], current state [" + state
0092:                                            + "]");
0093:                        }
0094:                    }
0095:                }
0096:
0097:                return callNextInterceptor(invocation);
0098:            }
0099:
0100:            /**
0101:             * This should return the list of interfaces that a decorator wishes to
0102:             * expose through the component proxy. This is used by the
0103:             * component factory to determine what interfaces the component proxy will
0104:             * implement.
0105:             *
0106:             * @return Class[] an array of interfaces
0107:             */
0108:            public Class[] getExposedInterfaces() {
0109:                return DefaultLifecycleInterceptor.EXPOSED_INTERFACES;
0110:            }
0111:
0112:            /**
0113:             * A reference to the Component instance that is being managed.
0114:             * final because once the interceptor in constructed, this should
0115:             * not change.
0116:             */
0117:            private final FunctionalInterface functionalImplementation;
0118:
0119:            /**
0120:             * The current state associated with the Component.  Access to this
0121:             * property must be synchronized.  Access only via get and set methods.
0122:             */
0123:            private LifecycleStateEnum currentState = LifecycleStateEnum.CREATING;
0124:
0125:            /**
0126:             * A reference to the component proxy invocation handler.
0127:             * Used to get a reference to the components monitor.
0128:             * final because once the interceptor in constructed,
0129:             * this should not change.
0130:             */
0131:            private final ComponentProxyInvocationHandler proxyInvocationHandler;
0132:
0133:            /** reference to the complete component */
0134:            private Component componentProxy;
0135:
0136:            /**
0137:             * lock object synchronized upon to block calls while in a suspended
0138:             * state, used in waitForResume and internalResumeComponent methods
0139:             */
0140:            private final Object suspendedLock = new Object();
0141:
0142:            /** timeout for blocking calls. */
0143:            private long blockedCallTimeout;
0144:
0145:            /** timeout for the destroyer thread. */
0146:            private long destroyerThreadTimeout;
0147:
0148:            /**
0149:             * Creates a new DefaultLifecycleInterceptor.
0150:             * Sets the initial state to CREATING.
0151:             * It is intended that the constructor does not accept as a parameter
0152:             * the Component to be managed, since this would circumvent the mutator
0153:             * method on the LifecycleInterceptor Interface.
0154:             *
0155:             * @param componentInstance instance of the component
0156:             * @param proxyInvocationHandler invocation handler for the component
0157:             * @param configuration configuration for the interceptor
0158:             */
0159:            public DefaultLifecycleInterceptor(
0160:                    FunctionalInterface componentInstance,
0161:                    ComponentProxyInvocationHandler proxyInvocationHandler,
0162:                    DefaultLifecycleInterceptorConfiguration configuration) {
0163:
0164:                this .functionalImplementation = componentInstance;
0165:
0166:                this .proxyInvocationHandler = proxyInvocationHandler;
0167:
0168:                if (configuration == null) {
0169:                    this .blockedCallTimeout = DefaultLifecycleInterceptorConfiguration.BlockedCallTimeout;
0170:                    this .destroyerThreadTimeout = DefaultLifecycleInterceptorConfiguration.DestroyerThreadTimeout;
0171:
0172:                } else {
0173:                    this .blockedCallTimeout = configuration
0174:                            .getBlockedCallTimeout();
0175:                    this .destroyerThreadTimeout = configuration
0176:                            .getDestroyerThreadTimeout();
0177:                }
0178:            }
0179:
0180:            /**
0181:             * Gets the current lifecycle state of the component.
0182:             * Note the protected corresponding mutator method - this property is
0183:             * read-only to external entities.
0184:             * @return the lifecycle state of this component
0185:             */
0186:            public synchronized LifecycleStateEnum getLifecycleState() {
0187:                return this .currentState;
0188:            }
0189:
0190:            /**
0191:             * Returns a string representation of the Lifecycle State
0192:             *
0193:             * @return a string representation of the Lifecycle State
0194:             */
0195:            public String getLifecycleStateString() {
0196:                return getLifecycleState().toString();
0197:            }
0198:
0199:            /**
0200:             * Sets the current lifecycle state
0201:             * @param state the new state
0202:             */
0203:            protected synchronized void setLifecycleState(
0204:                    LifecycleStateEnum state) {
0205:
0206:                if (log.isTraceEnabled()) {
0207:                    log.trace("Changing [" + getComponentName()
0208:                            + "] component's state from [" + this .currentState
0209:                            + "] to [" + state + "]");
0210:                }
0211:
0212:                // If the component template is so configured to have a decorator
0213:                // capable of sending events, then send one.
0214:                if (this .componentProxy instanceof  EventManager) {
0215:                    ((EventManager) this .componentProxy)
0216:                            .sendEvent(new ComponentEvent(this .componentProxy,
0217:                                    LIFECYCLE_CHANGE_EVENT_NAME,
0218:                                    "Lifecycle state is changing from ["
0219:                                            + this .currentState.getName()
0220:                                            + "] to [" + state.getName() + "]"));
0221:                }
0222:
0223:                this .currentState = state;
0224:            }
0225:
0226:            /**
0227:             * Run ONLY ONCE during the life of a Component, immediately after the
0228:             * Component is created. Enforced by having CREATING as the only allowed
0229:             * entry state.
0230:             *
0231:             * <p>Valid Entry States: CREATING </p>
0232:             * <p>Interim State: INITIALIZING</p>
0233:             * <p>Exit State: STOPPED</p>
0234:             *
0235:             * @param thisComponent component to be initialized
0236:             *
0237:             * @throws InvalidStateException When the entry state is not allowed
0238:             * @throws OperationNotSupportedException When component does not support
0239:             *         the requested operation
0240:             * @throws StateTransitionException When an error occured while trying to
0241:             *         complete the lifecycle operation
0242:             */
0243:            public void initializeComponent(Component this Component)
0244:                    throws InvalidStateException,
0245:
0246:                    OperationNotSupportedException, StateTransitionException {
0247:
0248:                startLifecycleMethod();
0249:
0250:                validateEntryState(
0251:                        getLifecycleState(),
0252:                        DefaultLifecycleInterceptor.VALID_ENTRY_STATES_INITIALIZE);
0253:
0254:                try {
0255:                    if (functionalImplementation instanceof  Initializable) {
0256:                        Initializable subject = null;
0257:                        //Cast the component to Initializable
0258:                        subject = (Initializable) functionalImplementation;
0259:                        //Immediately before calling initialize(),
0260:                        //set state to INITIALIZING
0261:                        setLifecycleState(LifecycleStateEnum.INITIALIZING);
0262:                        //Call the component's intialize() method
0263:                        subject.initialize(this Component);
0264:                    } else {
0265:                        logNotSupported(Initializable.class);
0266:                    }
0267:                    //Now move the state to STOPPED
0268:                    setLifecycleState(LifecycleStateEnum.STOPPED);
0269:
0270:                } catch (Exception e) {
0271:                    throw new StateTransitionException(
0272:                            this .getClass(),
0273:                            "An Exception occurred while attempting to initialize",
0274:                            e);
0275:
0276:                } finally {
0277:                    stopLifecycleMethod();
0278:                }
0279:            }
0280:
0281:            /**
0282:             * Tells the Component to begin providing its service.
0283:             *
0284:             * <p>Valid Entry States: STOPPED</p>
0285:             * <p>Interim State: STARTING</p>
0286:             * <p>Exit State: RUNNING</p>
0287:             *
0288:             * @throws InvalidStateException When the entry state is not allowed
0289:             * @throws OperationNotSupportedException When component does not support
0290:             * the requested operation
0291:             * @throws StateTransitionException When an error occured while trying to
0292:             * complete the lifecycle operation
0293:             */
0294:            public void startComponent() throws InvalidStateException,
0295:                    OperationNotSupportedException, StateTransitionException {
0296:
0297:                startLifecycleMethod();
0298:
0299:                validateEntryState(getLifecycleState(),
0300:                        DefaultLifecycleInterceptor.VALID_ENTRY_STATES_START);
0301:
0302:                try {
0303:
0304:                    if (functionalImplementation instanceof  Startable) {
0305:                        callComponentStart();
0306:                    } else {
0307:                        logNotSupported(Startable.class);
0308:                    }
0309:
0310:                    //Now move the state to RUNNING
0311:                    setLifecycleState(LifecycleStateEnum.RUNNING);
0312:
0313:                } finally {
0314:                    stopLifecycleMethod();
0315:                    // kill the component if it is in an interim state
0316:                    if (getLifecycleState() == LifecycleStateEnum.STARTING) {
0317:                        killInvalidComponent();
0318:                    }
0319:                }
0320:            }
0321:
0322:            /**
0323:             * Tells the Component to cease providing its service.
0324:             * This is an opportunity for the Component to complete outstanding
0325:             * work.
0326:             *
0327:             * <p>Valid Entry States: RUNNING, SUSPENDED</p>
0328:             * <p>Interim State: STOPPING</p>
0329:             * <p>Exit State: STOPPED</p>
0330:             *
0331:             * @throws InvalidStateException When the entry state is not allowed
0332:             * @throws OperationNotSupportedException When component does not support
0333:             * the requested operation
0334:             * @throws StateTransitionException When an error occured while trying to
0335:             * complete the lifecycle operation
0336:             */
0337:            public void stopComponent() throws InvalidStateException,
0338:                    OperationNotSupportedException, StateTransitionException {
0339:
0340:                startLifecycleMethod();
0341:
0342:                validateEntryState(getLifecycleState(),
0343:                        DefaultLifecycleInterceptor.VALID_ENTRY_STATES_STOP);
0344:
0345:                try {
0346:
0347:                    internalStopComponent();
0348:
0349:                } finally {
0350:                    stopLifecycleMethod();
0351:                    // kill the component if it is in an interim state
0352:                    if (getLifecycleState() == LifecycleStateEnum.STOPPING) {
0353:                        killInvalidComponent();
0354:                    }
0355:                }
0356:            }
0357:
0358:            /**
0359:             * Tells the Component to suspend its service. This is an opportunity for
0360:             * the Component to sensibly pause its outstanding work.
0361:             *
0362:             * <p>Valid Entry States: RUNNING</p>
0363:             * <p>Interim State: SUSPENDING</p>
0364:             * <p>Exit State: SUSPENDED</p>
0365:             *
0366:             * @throws InvalidStateException When the entry state is not allowed
0367:             * @throws OperationNotSupportedException When component does not support
0368:             * the requested operation
0369:             * @throws StateTransitionException When an error occured while trying to
0370:             * complete the lifecycle operation
0371:             */
0372:            public void suspendComponent() throws InvalidStateException,
0373:                    OperationNotSupportedException, StateTransitionException {
0374:
0375:                startLifecycleMethod();
0376:
0377:                validateEntryState(getLifecycleState(),
0378:                        DefaultLifecycleInterceptor.VALID_ENTRY_STATES_SUSPEND);
0379:
0380:                try {
0381:                    internalSuspendComponent();
0382:
0383:                } finally {
0384:                    stopLifecycleMethod();
0385:                    if (getLifecycleState() == LifecycleStateEnum.SUSPENDING) {
0386:                        killInvalidComponent();
0387:                    }
0388:                }
0389:            }
0390:
0391:            /**
0392:             * Tells the Component to resume its service. The Component can now continue
0393:             * its outstanding work.
0394:             *
0395:             * <p>Valid Entry States: SUSPENDED</p>
0396:             * <p>Interim State: RESUMING</p>
0397:             * <p>Exit State: RUNNING</p>
0398:             *
0399:             * @throws InvalidStateException When the entry state is not allowed
0400:             * @throws OperationNotSupportedException When component does not support
0401:             * the requested operation
0402:             * @throws StateTransitionException When an error occured while trying to
0403:             * complete the lifecycle operation
0404:             */
0405:            public void resumeComponent() throws InvalidStateException,
0406:                    OperationNotSupportedException, StateTransitionException {
0407:
0408:                startLifecycleMethod();
0409:
0410:                validateEntryState(getLifecycleState(),
0411:                        DefaultLifecycleInterceptor.VALID_ENTRY_STATES_RESUME);
0412:
0413:                try {
0414:                    internalResumeComponent();
0415:
0416:                    // Wake an who we're waiting while the component was suspended
0417:                    synchronized (this .suspendedLock) {
0418:                        this .suspendedLock.notifyAll();
0419:                    }
0420:                } finally {
0421:                    stopLifecycleMethod();
0422:                    if (getLifecycleState() == LifecycleStateEnum.RESUMING) {
0423:                        killInvalidComponent();
0424:                    }
0425:                }
0426:            }
0427:
0428:            /**
0429:             * Provides a Component with its Configuration. The Component should be
0430:             * SUSPENDED or STOPPED, if not already.
0431:             * The Component should also be returned to its entry state (RUNNING or
0432:             * SUSPENDED) after the main Configure operation has completed.
0433:             *
0434:             * <p>Valid Entry States: RUNNING, SUSPENDED, STOPPED</p>
0435:             * <p>Interim State: CONFIGURING</p>
0436:             * <p>Exit States: RUNNING, SUSPENDED, STOPPED (to match entry state)</p>
0437:             *
0438:             * @param configuration Configuration object to be applied to component
0439:             * @throws InvalidStateException When the entry state is not allowed
0440:             * @throws OperationNotSupportedException When component does not support
0441:             * the requested operation
0442:             * @throws StateTransitionException When an error occured while trying to
0443:             * complete the lifecycle operation
0444:             */
0445:            public void configureComponent(ComponentConfiguration configuration)
0446:                    throws InvalidStateException,
0447:                    OperationNotSupportedException, StateTransitionException {
0448:
0449:                startLifecycleMethod();
0450:
0451:                validateEntryState(
0452:                        getLifecycleState(),
0453:                        DefaultLifecycleInterceptor.VALID_ENTRY_STATES_CONFIGURE);
0454:
0455:                try {
0456:                    if (functionalImplementation instanceof  Configurable) {
0457:                        callComponentConfigure(configuration);
0458:
0459:                    } else {
0460:                        logNotSupported(Configurable.class);
0461:                    }
0462:
0463:                } finally {
0464:                    stopLifecycleMethod();
0465:
0466:                    LifecycleStateEnum exitState = getLifecycleState();
0467:                    if (exitState != LifecycleStateEnum.RUNNING
0468:                            && exitState != LifecycleStateEnum.SUSPENDED
0469:                            && exitState != LifecycleStateEnum.STOPPED) {
0470:
0471:                        killInvalidComponent();
0472:                    }
0473:                }
0474:            }
0475:
0476:            /**
0477:             * Tells the Component prepare to die. This is an opportunity for the
0478:             * developer to do some sensible housekeeping to aid Garbage Collection,
0479:             * relinquish resources etc. Once in the DESTROYED state, a Component
0480:             * cannot be revived.  This implementation will wait for
0481:             * DESTROY_TIMEOUT_MILLIS for the component to be destroyed.  If, after
0482:             * that time the component has not been destroyed, it will be logged as
0483:             * a warning.
0484:             *
0485:             * <p>Valid Entry States: All states are valid for entry.  If the
0486:             * component is in the RUNNING state, it will be stopped first.</p>
0487:             * <p>Interim State: DESTROYING</p>
0488:             * <p>Exit State: DESTROYED</p>
0489:             *
0490:             * @throws InvalidStateException When the entry state is not allowed
0491:             * @throws OperationNotSupportedException When component does not support
0492:             * the requested operation
0493:             * @throws StateTransitionException When an error occured while trying to
0494:             * complete the lifecycle operation
0495:             */
0496:            public void destroyComponent()
0497:                    throws OperationNotSupportedException,
0498:                    StateTransitionException {
0499:
0500:                if (getLifecycleState() == LifecycleStateEnum.DESTROYED) {
0501:                    // component already destroyed
0502:                    return;
0503:                }
0504:
0505:                startLifecycleMethod();
0506:
0507:                try {
0508:                    if (functionalImplementation instanceof  Destroyable
0509:                            || (getLifecycleState() == LifecycleStateEnum.RUNNING && functionalImplementation instanceof  Startable)) {
0510:
0511:                        //Create an anonymous thread that we will use
0512:                        //to timeout on the destroy operation
0513:                        Thread destroyer = new Thread(new Runnable() {
0514:                            public void run() {
0515:                                try {
0516:                                    // stop the component if it is running
0517:                                    if (getLifecycleState() == LifecycleStateEnum.RUNNING) {
0518:
0519:                                        internalStopComponent();
0520:                                    }
0521:
0522:                                    //Call the component's destroy() method
0523:                                    if (functionalImplementation instanceof  Destroyable) {
0524:
0525:                                        // Immediately before calling destroy(),
0526:                                        // set state to DESTROYING
0527:                                        setLifecycleState(LifecycleStateEnum.DESTROYING);
0528:
0529:                                        ((Destroyable) functionalImplementation)
0530:                                                .destroy();
0531:                                    }
0532:                                } catch (Exception e) {
0533:                                    log
0534:                                            .warn("Exception destroying component ["
0535:                                                    + getComponentName()
0536:                                                    + "]: "
0537:                                                    + e
0538:                                                    + ": "
0539:                                                    + ExceptionUtility
0540:                                                            .printStackTracesToString(e));
0541:                                }
0542:                            }
0543:                        }, "Destroying component " + getComponentName());
0544:
0545:                        // set the thread to a daemon so it won't halt shutdown
0546:                        destroyer.setDaemon(true);
0547:                        destroyer.start();
0548:
0549:                        //Join the thread with a specified timeout
0550:                        destroyer.join(this .destroyerThreadTimeout);
0551:
0552:                        //On timeout, if the destroyer thread is still running
0553:                        //throw an Exception
0554:                        if (destroyer.isAlive()) {
0555:                            String message = "Destroy operation timed out after "
0556:                                    + this .destroyerThreadTimeout
0557:                                    + " milliseconds";
0558:
0559:                            log.warn(message);
0560:                        }
0561:                    } else {
0562:                        logNotSupported(Destroyable.class);
0563:                    }
0564:
0565:                    //Now move the state to DESTROYED
0566:                    setLifecycleState(LifecycleStateEnum.DESTROYED);
0567:
0568:                } catch (InterruptedException ie) {
0569:                    String message = "Thread interrupted during attempt to destroy";
0570:                    throw new StateTransitionException(this .getClass(),
0571:                            message, ie);
0572:
0573:                } catch (Exception e) {
0574:                    String message = "An error occurred while attempting to destroy";
0575:                    throw new StateTransitionException(this .getClass(),
0576:                            message, e);
0577:
0578:                } finally {
0579:                    stopLifecycleMethod();
0580:                }
0581:            }
0582:
0583:            /**
0584:             * This implementation does not make use of the componentProxy reference
0585:             *
0586:             * @param componentProxy a reference to the component that
0587:             *        this interceptor is assisting
0588:             */
0589:            public void setComponentReference(Component componentProxy) {
0590:                this .componentProxy = componentProxy;
0591:            }
0592:
0593:            /**
0594:             * Acquires the component's monitor for writing.  If this method is
0595:             * called, it is imperitive that stopLifecycleMethod() is called.
0596:             * <p>
0597:             * Example invocation:<br>
0598:             * <pre><code>
0599:             * startLifecycleMethod();
0600:             * try {
0601:             *     ...
0602:             * } finally {
0603:             *     stopLifecycleMethod();
0604:             * }
0605:             * </code></pre>
0606:             *
0607:             * @see ComponentProxyInvocationHandler#getMonitor()
0608:             *
0609:             * @throws StateTransitionException if the Thread is interrupted
0610:             */
0611:            protected void startLifecycleMethod() {
0612:                if (log.isTraceEnabled()) {
0613:                    log
0614:                            .trace("Acquiring lock to start lifecycle method on component ["
0615:                                    + getComponentName() + "]");
0616:                }
0617:
0618:                try {
0619:                    this .proxyInvocationHandler.getMonitor().writeLock()
0620:                            .attempt(1000);
0621:                } catch (InterruptedException ie) {
0622:                    throw new StateTransitionException(this .getClass(),
0623:                            "Caught InterruptedException while trying to acquire the "
0624:                                    + "component's monitor", ie);
0625:                }
0626:            }
0627:
0628:            /** Releases the component's monitor */
0629:            protected void stopLifecycleMethod() {
0630:                if (log.isTraceEnabled()) {
0631:                    log
0632:                            .trace("Releasing lifecycle method write lock on component ["
0633:                                    + getComponentName() + "]");
0634:                }
0635:                this .proxyInvocationHandler.getMonitor().writeLock().release();
0636:            }
0637:
0638:            /**
0639:             * Helper method to do the work of suspending a component.  Called by
0640:             * suspendComponent and configureComponent.  A helper method is used
0641:             * so that calling methods can handle threading issues as they require
0642:             * while not duplicating code
0643:             *
0644:             * @throws StateTransitionException if an exception is caught in the
0645:             * functional implementations suspend method
0646:             * @throws OperationNotSupportedException not thrown by this imlementation,
0647:             * but provided for overriding methods
0648:             */
0649:            protected void internalSuspendComponent()
0650:                    throws OperationNotSupportedException,
0651:                    StateTransitionException {
0652:
0653:                if (functionalImplementation instanceof  Suspendable) {
0654:                    callComponentSuspend();
0655:
0656:                } else {
0657:                    logNotSupported(Suspendable.class);
0658:                }
0659:
0660:                //Now move the state to SUSPENDED
0661:                setLifecycleState(LifecycleStateEnum.SUSPENDED);
0662:            }
0663:
0664:            /**
0665:             * Helper method to do the work of resuming a component.  Called by
0666:             * resumeComponent and configureComponent.  A helper method is used
0667:             * so that calling methods can handle threading issues as they require
0668:             * while not duplicating code
0669:             *
0670:             * @throws StateTransitionException if an exception is caught in the
0671:             * functional implementations resume method
0672:             * @throws OperationNotSupportedException not thrown by this imlementation,
0673:             * but provided for overriding methods
0674:             */
0675:            protected void internalResumeComponent()
0676:                    throws OperationNotSupportedException,
0677:                    StateTransitionException {
0678:
0679:                if (functionalImplementation instanceof  Suspendable) {
0680:                    callComponentResume();
0681:
0682:                } else {
0683:                    logNotSupported(Suspendable.class);
0684:                }
0685:
0686:                //Now move the state to RUNNING
0687:                setLifecycleState(LifecycleStateEnum.RUNNING);
0688:            }
0689:
0690:            /**
0691:             * Helper method to do the work of suspending a component.  Called by
0692:             * suspendComponent and configureComponent.  A helper method is used
0693:             * so that calling methods can handle threading issues as they require
0694:             * while not duplicating code
0695:             *
0696:             * @throws StateTransitionException if an exception is caught in the
0697:             * functional implementations suspend method
0698:             * @throws OperationNotSupportedException not thrown by this imlementation,
0699:             * but provided for overriding methods
0700:             */
0701:            protected void internalStopComponent()
0702:                    throws OperationNotSupportedException,
0703:                    StateTransitionException {
0704:
0705:                if (functionalImplementation instanceof  Startable) {
0706:                    callComponentStop();
0707:
0708:                } else {
0709:                    logNotSupported(Startable.class);
0710:                }
0711:
0712:                //Now move the state to SUSPENDED
0713:                setLifecycleState(LifecycleStateEnum.STOPPED);
0714:            }
0715:
0716:            /**
0717:             * Waits for the component to return from the LifecycleStateEnum.SUSPENDED
0718:             * state to the LifecycleStateEnum.RUNNING state.
0719:             * <p>
0720:             * Override this method to disable or change this functionality.
0721:             *
0722:             * @throws ComponentUnavailableException if it does not change states in a
0723:             * timely manner or if
0724:             * @throws InvalidStateException if the entry state is not within
0725:             *   the Set of validStates
0726:             */
0727:            protected void waitForResume() throws InvalidStateException,
0728:                    ComponentUnavailableException {
0729:
0730:                if (log.isTraceEnabled()) {
0731:                    log.trace("Component [" + this .getComponentName()
0732:                            + "] suspended, waiting for it to resume");
0733:                }
0734:
0735:                try {
0736:                    // need to release the read monitor to prevent deadlock
0737:                    // this monitor is claimed within the proxyInvocationHandler
0738:                    this .proxyInvocationHandler.getMonitor().readLock()
0739:                            .release();
0740:
0741:                    synchronized (suspendedLock) {
0742:                        if (getLifecycleState() == LifecycleStateEnum.SUSPENDED) {
0743:                            suspendedLock.wait(this .blockedCallTimeout);
0744:                        }
0745:                    }
0746:
0747:                } catch (InterruptedException ie) {
0748:                    Thread.currentThread().interrupt();
0749:                    log.warn("Caught InterruptedException: "
0750:                            + ExceptionUtility.printStackTracesToString(ie));
0751:
0752:                } finally {
0753:                    // restore the read monitor
0754:                    try {
0755:                        this .proxyInvocationHandler.getMonitor().readLock()
0756:                                .acquire();
0757:                    } catch (InterruptedException ie) {
0758:                        Thread.currentThread().interrupt();
0759:                        throw new MonitorAcquisitionException(
0760:                                this .getClass(),
0761:                                "Caught InterruptedException reaquiring the monitor",
0762:                                ie);
0763:                    }
0764:                    if (getLifecycleState() != LifecycleStateEnum.RUNNING) {
0765:                        String message = "Call to component timed out because it was in a "
0766:                                + "transient lifecycle state, and did not return to "
0767:                                + "RUNNING state soon enough to service the call "
0768:                                + "or another thread changed the state before this one "
0769:                                + "could execute the method call.";
0770:                        throw new ComponentUnavailableException(
0771:                                this .getClass(), message);
0772:                    }
0773:                }
0774:            }
0775:
0776:            /**
0777:             * Checks if a given state exists in a set of valid states.
0778:             * @param entryState the entry state to be validated
0779:             * @param validStates a set of validStates
0780:             * @throws InvalidStateException if the entry state is not within
0781:             *   the Set of validStates
0782:             */
0783:            protected final void validateEntryState(
0784:                    LifecycleStateEnum entryState, Set validStates) {
0785:
0786:                if (!validStates.contains(entryState)) {
0787:                    final String message = "The requested lifecycle operation can not be performed "
0788:                            + "while in this state: [" + entryState + "]";
0789:
0790:                    throw new InvalidStateException(this .getClass(), message);
0791:                }
0792:            }
0793:
0794:            /**
0795:             * Utility method to log trace details when a component does not
0796:             * support an attempted lifecycle operation.
0797:             *
0798:             * @param unImplementedInterface the interface which held the lifecycle
0799:             *    method that was not implemented by the component
0800:             */
0801:            protected final void logNotSupported(Class unImplementedInterface) {
0802:
0803:                if (log.isTraceEnabled()) {
0804:                    log
0805:                            .trace("Cannot notify component of lifecycle operation. ["
0806:                                    + getComponentName()
0807:                                    + "] does not implement ["
0808:                                    + unImplementedInterface.getName() + "]");
0809:                }
0810:            }
0811:
0812:            /**
0813:             * Utility method used to get the component's name
0814:             *
0815:             * @return String the name of the component
0816:             */
0817:            protected final String getComponentName() {
0818:                if (this .componentProxy == null) {
0819:                    return null;
0820:                } else {
0821:                    return this .componentProxy.getComponentName();
0822:                }
0823:            }
0824:
0825:            /**
0826:             * <p>
0827:             * This method is called when an exception other than
0828:             * NonFatalStateTransitionException is thrown from a component's lifecycle
0829:             * method which signals that the component is corrupt and should be
0830:             * destroyed.
0831:             * </p>
0832:             * <p>
0833:             * Override this method to change what happens to a component if it
0834:             * fails to transition state.
0835:             * </p>
0836:             */
0837:            protected void killInvalidComponent() {
0838:                if (log.isInfoEnabled()) {
0839:                    log.info("Destroying component [" + getComponentName()
0840:                            + "], it is in an unexpected state ["
0841:                            + getLifecycleState() + "]");
0842:                }
0843:                destroyComponent();
0844:            }
0845:
0846:            /**
0847:             * Calls component's lifecycle method.  Manages state transitions
0848:             * from entry state to interim state.  It will also return the component
0849:             * to its entry state if a NonFatalStateTransitionException is caught.
0850:             */
0851:            private void callComponentStart() {
0852:                LifecycleStateEnum entryState = getLifecycleState();
0853:                try {
0854:                    Startable subject = null;
0855:                    //Cast the component to Startable
0856:                    subject = (Startable) functionalImplementation;
0857:                    //Immediately before calling start(), set state to STARTING
0858:                    setLifecycleState(LifecycleStateEnum.STARTING);
0859:                    //Call the component's start() method
0860:                    subject.start();
0861:
0862:                } catch (NonFatalStateTransitionException nfste) {
0863:                    log
0864:                            .info("Caught NonFatalStateTransitionException, "
0865:                                    + "returning component to its original state. Component: ["
0866:                                    + getComponentName() + "]");
0867:
0868:                    setLifecycleState(entryState);
0869:                    // propagate exception
0870:                    throw nfste;
0871:
0872:                } catch (Exception e) {
0873:                    String message = "An Exception occurred while attempting to start ["
0874:                            + getComponentName() + "]";
0875:                    throw new StateTransitionException(this .getClass(),
0876:                            message, e);
0877:                }
0878:            }
0879:
0880:            /**
0881:             * Calls component's lifecycle method.  Manages state transitions
0882:             * from entry state to interim state.  It will also return the component
0883:             * to its entry state if a NonFatalStateTransitionException is caught.
0884:             */
0885:            private void callComponentStop() {
0886:                LifecycleStateEnum entryState = getLifecycleState();
0887:                try {
0888:                    Startable subject = null;
0889:                    //Cast the component to Startable
0890:                    subject = (Startable) functionalImplementation;
0891:                    //Immediately before calling stop(), set state to STOPPING
0892:                    setLifecycleState(LifecycleStateEnum.STOPPING);
0893:                    //Call the component's stop() method
0894:                    subject.stop();
0895:
0896:                } catch (NonFatalStateTransitionException nfste) {
0897:                    log
0898:                            .info("Caught NonFatalStateTransitionException, "
0899:                                    + "returning component to its original state. Component: ["
0900:                                    + getComponentName() + "]");
0901:
0902:                    setLifecycleState(entryState);
0903:                    // propagate exception
0904:                    throw nfste;
0905:
0906:                } catch (Exception e) {
0907:                    String message = "An Exception occurred while attempting to stop ["
0908:                            + getComponentName() + "]";
0909:                    throw new StateTransitionException(this .getClass(),
0910:                            message, e);
0911:                }
0912:            }
0913:
0914:            /**
0915:             * Calls component's lifecycle method.  Manages state transitions
0916:             * from entry state to interim state, suspending or resuming as necessary.
0917:             * It will also return the component
0918:             * to its last good state (RUNNING or SUSPENDED depending on where the
0919:             * exception was thrown) if a NonFatalStateTransitionException is caught.
0920:             *
0921:             * @param configuration configuration for this component that will be
0922:             *        passed to its lifecycle method
0923:             */
0924:            private void callComponentConfigure(
0925:                    ComponentConfiguration configuration) {
0926:                LifecycleStateEnum entryState = getLifecycleState();
0927:                LifecycleStateEnum lastGoodState = entryState;
0928:                try {
0929:                    //Cast the component to Configurable
0930:                    Configurable subject = (Configurable) functionalImplementation;
0931:
0932:                    //if was RUNNING then suspend it
0933:                    if (entryState == LifecycleStateEnum.RUNNING) {
0934:                        internalSuspendComponent();
0935:                        lastGoodState = getLifecycleState();
0936:                    }
0937:
0938:                    //Immediately before calling configure(),
0939:                    //set state to CONFIGURING
0940:                    setLifecycleState(LifecycleStateEnum.CONFIGURING);
0941:
0942:                    //Call the component's configure method
0943:                    subject.configure(configuration);
0944:
0945:                    if (entryState == LifecycleStateEnum.RUNNING) {
0946:                        //if was RUNNING then call resume to move it back
0947:                        internalResumeComponent();
0948:                    } else {
0949:                        //otherwise, move it back to its original state
0950:                        this .setLifecycleState(entryState);
0951:                    }
0952:
0953:                } catch (NonFatalStateTransitionException nfste) {
0954:                    log
0955:                            .info("Caught NonFatalStateTransitionException, "
0956:                                    + "returning component to its original state. Component: ["
0957:                                    + getComponentName() + "]");
0958:
0959:                    setLifecycleState(lastGoodState);
0960:                    // propagate exception
0961:                    throw nfste;
0962:
0963:                } catch (Exception e) {
0964:                    String message = "An Exception occurred while attempting to configure ["
0965:                            + getComponentName() + "]";
0966:                    throw new StateTransitionException(this .getClass(),
0967:                            message, e);
0968:                }
0969:            }
0970:
0971:            /**
0972:             * Calls component's lifecycle method.  Manages state transitions
0973:             * from entry state to interim state.  It will also return the component
0974:             * to its entry state if a NonFatalStateTransitionException is caught.
0975:             */
0976:            private void callComponentSuspend() {
0977:                LifecycleStateEnum entryState = getLifecycleState();
0978:                try {
0979:                    Suspendable subject = null;
0980:                    //Cast the component to Startable
0981:                    subject = (Suspendable) functionalImplementation;
0982:                    //Immediately before calling suspend(), set state to SUSPENDING
0983:                    setLifecycleState(LifecycleStateEnum.SUSPENDING);
0984:                    //Call the component's suspend() method
0985:                    subject.suspend();
0986:
0987:                } catch (NonFatalStateTransitionException nfste) {
0988:                    log
0989:                            .info("Caught NonFatalStateTransitionException, "
0990:                                    + "returning component to its original state. Component: ["
0991:                                    + getComponentName() + "]");
0992:
0993:                    setLifecycleState(entryState);
0994:                    // propagate exception
0995:                    throw nfste;
0996:
0997:                } catch (Exception e) {
0998:                    String message = "An Exception occurred while attempting to suspend ["
0999:                            + getComponentName() + "]";
1000:                    throw new StateTransitionException(getClass(), message, e);
1001:                }
1002:            }
1003:
1004:            /**
1005:             * Calls component's lifecycle method.  Manages state transitions
1006:             * from entry state to interim state.  It will also return the component
1007:             * to its entry state if a NonFatalStateTransitionException is caught.
1008:             */
1009:            private void callComponentResume() {
1010:                LifecycleStateEnum entryState = getLifecycleState();
1011:                try {
1012:                    Suspendable subject = null;
1013:                    //Cast the component to Startable
1014:                    subject = (Suspendable) functionalImplementation;
1015:                    //Immediately before calling resume(), set state to RESUMING
1016:                    setLifecycleState(LifecycleStateEnum.RESUMING);
1017:                    //Call the component's resume() method
1018:                    subject.resume();
1019:
1020:                } catch (NonFatalStateTransitionException nfste) {
1021:                    log
1022:                            .info("Caught NonFatalStateTransitionException, "
1023:                                    + "returning component to its original state. Component: ["
1024:                                    + getComponentName() + "]");
1025:
1026:                    setLifecycleState(entryState);
1027:                    // propagate exception
1028:                    throw nfste;
1029:
1030:                } catch (Exception e) {
1031:                    String message = "An Exception occurred while attempting to resume ["
1032:                            + getComponentName() + "]";
1033:                    throw new StateTransitionException(this .getClass(),
1034:                            message, e);
1035:                }
1036:            }
1037:
1038:            /* Static Members, Initializers and Methods below here */
1039:
1040:            /** Defines the valid initialize states */
1041:            private static final Set VALID_ENTRY_STATES_INITIALIZE;
1042:            /** Defines the valid start states */
1043:            private static final Set VALID_ENTRY_STATES_START;
1044:            /** Defines the valid stop states */
1045:            private static final Set VALID_ENTRY_STATES_STOP;
1046:            /** Defines the valid suspend states */
1047:            private static final Set VALID_ENTRY_STATES_SUSPEND;
1048:            /** Defines the valid resume states */
1049:            private static final Set VALID_ENTRY_STATES_RESUME;
1050:            /** Defines the valid configure states */
1051:            private static final Set VALID_ENTRY_STATES_CONFIGURE;
1052:
1053:            static {
1054:
1055:                /*
1056:                 * Below, Sets are created, containing the valid entry states for
1057:                 * each lifecycle operation. When there is only one valid entry state,
1058:                 * we use a Singleton Set. When there is more than one valid entry state
1059:                 * we use a new HashSet. I would consider using a TreeSet in place of
1060:                 * HashSet if storage were crucial, but unless storage is in issue, lets
1061:                 * stick with HashSet's O(1) performance on Set.contains(Object o)
1062:                 * operations.
1063:                 */
1064:
1065:                /* Set the valid entry states for initialize() */
1066:                VALID_ENTRY_STATES_INITIALIZE = Collections
1067:                        .singleton(LifecycleStateEnum.CREATING);
1068:
1069:                /* Set the valid entry states for start() */
1070:                VALID_ENTRY_STATES_START = Collections
1071:                        .singleton(LifecycleStateEnum.STOPPED);
1072:
1073:                /* Set the valid entry states for stop() */
1074:                HashSet validStates = new HashSet();
1075:                validStates.add(LifecycleStateEnum.RUNNING);
1076:                validStates.add(LifecycleStateEnum.SUSPENDED);
1077:                VALID_ENTRY_STATES_STOP = validStates;
1078:
1079:                /* Set the valid entry states for suspend() */
1080:                VALID_ENTRY_STATES_SUSPEND = Collections
1081:                        .singleton(LifecycleStateEnum.RUNNING);
1082:
1083:                /* Set the valid entry states for resume() */
1084:                VALID_ENTRY_STATES_RESUME = Collections
1085:                        .singleton(LifecycleStateEnum.SUSPENDED);
1086:
1087:                /* Set the valid entry states for configure() */
1088:                validStates = new HashSet();
1089:                validStates.add(LifecycleStateEnum.RUNNING);
1090:                validStates.add(LifecycleStateEnum.SUSPENDED);
1091:                validStates.add(LifecycleStateEnum.STOPPED);
1092:                VALID_ENTRY_STATES_CONFIGURE = validStates;
1093:            }
1094:
1095:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.