001: /*
002: * $Id: GenericLifecycleManager.java 11149 2008-03-03 19:41:55Z acooke $
003: * --------------------------------------------------------------------------------------
004: * Copyright (c) MuleSource, Inc. All rights reserved. http://www.mulesource.com
005: *
006: * The software in this package is published under the terms of the CPAL v1.0
007: * license, a copy of which has been included with this distribution in the
008: * LICENSE.txt file.
009: */
010: package org.mule.lifecycle;
011:
012: import org.mule.api.MuleException;
013: import org.mule.api.MuleContext;
014: import org.mule.api.lifecycle.LifecycleManager;
015: import org.mule.api.lifecycle.LifecyclePhase;
016: import org.mule.api.lifecycle.LifecycleTransitionResult;
017: import org.mule.lifecycle.phases.NotInLifecyclePhase;
018: import org.mule.util.StringMessageUtils;
019:
020: import java.util.HashMap;
021: import java.util.HashSet;
022: import java.util.Iterator;
023: import java.util.Map;
024: import java.util.Set;
025:
026: import org.apache.commons.collections.set.ListOrderedSet;
027: import org.apache.commons.logging.Log;
028: import org.apache.commons.logging.LogFactory;
029:
030: public class GenericLifecycleManager implements LifecycleManager {
031: /**
032: * logger used by this class
033: */
034: protected transient final Log logger = LogFactory
035: .getLog(GenericLifecycleManager.class);
036: protected static NotInLifecyclePhase notInLifecyclePhase = new NotInLifecyclePhase();
037: protected String currentPhase = notInLifecyclePhase.getName();
038: protected String executingPhase = null;
039: protected ListOrderedSet lifecycles = new ListOrderedSet();
040: protected Map index = new HashMap(6);
041: protected Set completedPhases = new HashSet(6);
042:
043: public Set getLifecycles() {
044: return lifecycles;
045: }
046:
047: public void setLifecycles(Set lifecycles) {
048: for (Iterator iterator = lifecycles.iterator(); iterator
049: .hasNext();) {
050: LifecyclePhase phase = (LifecyclePhase) iterator.next();
051: registerLifecycle(phase);
052: }
053:
054: }
055:
056: public void registerLifecycle(LifecyclePhase lci) {
057: index.put(lci.getName(), new Integer(lifecycles.size()));
058: lifecycles.add(lci);
059: }
060:
061: public void firePhase(MuleContext muleContext, String phase)
062: throws MuleException {
063: if (currentPhase.equalsIgnoreCase(phase)) {
064: logger.debug("Already in lifecycle phase: " + phase);
065: return;
066: }
067: Integer phaseIndex = (Integer) index.get(phase);
068: if (phaseIndex == null) {
069: throw new IllegalArgumentException(
070: "No lifeccycle phase registered with name: "
071: + phase);
072: }
073: try {
074: setExecutingPhase(phase);
075: LifecyclePhase li = (LifecyclePhase) lifecycles
076: .get(phaseIndex.intValue());
077: li.fireLifecycle(muleContext, currentPhase);
078: setCurrentPhase(li);
079: } finally {
080: setExecutingPhase(null);
081: }
082: }
083:
084: public String getCurrentPhase() {
085: return currentPhase;
086: }
087:
088: /**
089: * Returns the name of the currently executing phase or null if there is not current phase
090: *
091: * @return
092: */
093: public String getExecutingPhase() {
094: return executingPhase;
095: }
096:
097: protected synchronized void setCurrentPhase(LifecyclePhase phase) {
098: completedPhases.add(phase.getName());
099: completedPhases.remove(phase.getOppositeLifecyclePhase());
100: this .currentPhase = phase.getName();
101: }
102:
103: protected synchronized void setExecutingPhase(String phase) {
104: this .executingPhase = phase;
105: }
106:
107: public void reset() {
108: setExecutingPhase(null);
109: completedPhases.clear();
110: setCurrentPhase(notInLifecyclePhase);
111: }
112:
113: public boolean isPhaseComplete(String phaseName) {
114: return completedPhases.contains(phaseName);
115: }
116:
117: public void applyLifecycle(MuleContext muleContext, Object object)
118: throws MuleException {
119: logger.debug("applying lifecycle to " + object);
120: LifecyclePhase lcp;
121: String phase;
122: Integer phaseIndex;
123: for (Iterator iterator = completedPhases.iterator(); iterator
124: .hasNext();) {
125: phase = (String) iterator.next();
126: phaseIndex = (Integer) index.get(phase);
127: lcp = (LifecyclePhase) lifecycles
128: .get(phaseIndex.intValue());
129: logger.debug("phase: " + lcp);
130: LifecycleTransitionResult result = lcp
131: .applyLifecycle(object);
132: if (!LifecycleTransitionResult.isOk(result)) {
133: throw result.nestedRetryLifecycleException();
134: }
135: }
136: //If we're currently in a phase, fire that too
137: if (getExecutingPhase() != null) {
138: phaseIndex = (Integer) index.get(getExecutingPhase());
139: lcp = (LifecyclePhase) lifecycles
140: .get(phaseIndex.intValue());
141: logger.debug("and executing: " + lcp);
142: LifecycleTransitionResult result = lcp
143: .applyLifecycle(object);
144: if (!LifecycleTransitionResult.isOk(result)) {
145: throw result.nestedRetryLifecycleException();
146: }
147: }
148: }
149:
150: public void checkPhase(String name) throws IllegalStateException {
151: if (completedPhases.contains(name)) {
152: throw new IllegalStateException("Phase '" + name
153: + "' has already been executed");
154: }
155:
156: if (name.equalsIgnoreCase(executingPhase)) {
157: throw new IllegalStateException("Phase '" + name
158: + "' is already currently being executed");
159: }
160:
161: if (executingPhase != null) {
162: throw new IllegalStateException(
163: "Currently executing lifecycle phase: "
164: + executingPhase);
165: }
166:
167: Integer phaseIndex = (Integer) index.get(name);
168: if (phaseIndex == null) {
169: throw new IllegalStateException("Phase does not exist: "
170: + name);
171: }
172: if (NotInLifecyclePhase.PHASE_NAME.equals(currentPhase)) {
173: if (phaseIndex.intValue() > 0) {
174: throw new IllegalStateException(
175: "The first lifecycle phase has to be called before the '"
176: + name + "' phase");
177: }
178: } else {
179: LifecyclePhase phase = (LifecyclePhase) lifecycles
180: .get(phaseIndex.intValue());
181: if (!phase.isPhaseSupported(currentPhase)) {
182: throw new IllegalStateException("Lifecycle phase: "
183: + currentPhase
184: + " does not support current phase: "
185: + name
186: + ". Phases supported are: "
187: + StringMessageUtils.toString(phase
188: .getSupportedPhases()));
189: }
190: }
191: }
192: }
|