001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one
003: * or more contributor license agreements. See the NOTICE file
004: * distributed with this work for additional information
005: * regarding copyright ownership. The ASF licenses this file
006: * to you under the Apache License, Version 2.0 (the
007: * "License"); you may not use this file except in compliance
008: * with the License. You may obtain a copy of the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing,
013: * software distributed under the License is distributed on an
014: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015: * KIND, either express or implied. See the License for the
016: * specific language governing permissions and limitations
017: * under the License.
018: */
019:
020: package org.apache.myfaces.lifecycle;
021:
022: import java.util.HashMap;
023: import java.util.Map;
024: import javax.faces.context.FacesContext;
025: import javax.faces.event.PhaseEvent;
026: import javax.faces.event.PhaseId;
027: import javax.faces.event.PhaseListener;
028: import javax.faces.lifecycle.Lifecycle;
029: import org.apache.commons.logging.Log;
030: import org.apache.commons.logging.LogFactory;
031:
032: /**
033: * This class encapsulates the logic used to call PhaseListeners. It was
034: * needed because of issue 9 of the JSF 1.2 spec. See section 11.3 for more
035: * details.
036: *
037: * @author Stan Silvert
038: */
039: class PhaseListenerManager {
040:
041: private static final Log log = LogFactory
042: .getLog(PhaseListenerManager.class);
043:
044: private Lifecycle lifecycle;
045: private FacesContext facesContext;
046: private PhaseListener[] phaseListeners;
047:
048: // Tracks success in the beforePhase. Listeners that throw an exception
049: // in beforePhase or were never called because a previous listener threw
050: // an exception should not have its afterPhase called
051: private Map<PhaseId, boolean[]> listenerSuccessMap = new HashMap<PhaseId, boolean[]>();
052:
053: /** Creates a new instance of PhaseListenerManager */
054: PhaseListenerManager(Lifecycle lifecycle,
055: FacesContext facesContext, PhaseListener[] phaseListeners) {
056: this .lifecycle = lifecycle;
057: this .facesContext = facesContext;
058: this .phaseListeners = phaseListeners;
059: }
060:
061: private boolean isListenerForThisPhase(PhaseListener phaseListener,
062: PhaseId phaseId) {
063: int listenerPhaseId = phaseListener.getPhaseId().getOrdinal();
064: return (listenerPhaseId == PhaseId.ANY_PHASE.getOrdinal() || listenerPhaseId == phaseId
065: .getOrdinal());
066: }
067:
068: void informPhaseListenersBefore(PhaseId phaseId) {
069: boolean[] beforePhaseSuccess = new boolean[phaseListeners.length];
070: listenerSuccessMap.put(phaseId, beforePhaseSuccess);
071:
072: for (int i = 0; i < phaseListeners.length; i++) {
073: PhaseListener phaseListener = phaseListeners[i];
074: if (isListenerForThisPhase(phaseListener, phaseId)) {
075: try {
076: phaseListener.beforePhase(new PhaseEvent(
077: facesContext, phaseId, lifecycle));
078: beforePhaseSuccess[i] = true;
079: } catch (Exception e) {
080: beforePhaseSuccess[i] = false; // redundant - for clarity
081: log.error("Exception in PhaseListener "
082: + phaseId.toString() + " beforePhase.", e);
083: return;
084: }
085: }
086: }
087: }
088:
089: void informPhaseListenersAfter(PhaseId phaseId) {
090: boolean[] beforePhaseSuccess = listenerSuccessMap.get(phaseId);
091:
092: for (int i = phaseListeners.length - 1; i >= 0; i--) {
093: PhaseListener phaseListener = phaseListeners[i];
094: if (isListenerForThisPhase(phaseListener, phaseId)
095: && beforePhaseSuccess[i]) {
096: try {
097: phaseListener.afterPhase(new PhaseEvent(
098: facesContext, phaseId, lifecycle));
099: } catch (Exception e) {
100: log.error("Exception in PhaseListener "
101: + phaseId.toString() + " afterPhase", e);
102: }
103: }
104: }
105:
106: }
107: }
|