/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.deltaspike.jsf.impl.listener.phase; import org.apache.deltaspike.core.spi.activation.Deactivatable; import org.apache.deltaspike.core.util.ClassDeactivationUtils; import org.apache.deltaspike.core.util.ProxyUtils; import org.apache.deltaspike.jsf.api.listener.phase.AfterPhase; import org.apache.deltaspike.jsf.api.listener.phase.BeforePhase; import org.apache.deltaspike.jsf.api.listener.phase.JsfPhaseId; import org.apache.deltaspike.jsf.api.listener.phase.JsfPhaseListener; import javax.enterprise.context.ApplicationScoped; import javax.enterprise.event.Event; import javax.enterprise.inject.Instance; import javax.faces.event.PhaseEvent; import javax.faces.event.PhaseId; import javax.faces.event.PhaseListener; import javax.inject.Inject; import java.lang.annotation.Annotation; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.ListIterator; @ApplicationScoped public class JsfRequestLifecycleBroadcaster { @Inject private Event<PhaseEvent> phaseEvent; @Inject @BeforePhase(JsfPhaseId.ANY_PHASE) private Event<PhaseEvent> beforeAnyPhaseEvent; @Inject @AfterPhase(JsfPhaseId.ANY_PHASE) private Event<PhaseEvent> afterAnyPhaseEvent; private List<PhaseListener> phaseListeners = new ArrayList<PhaseListener>(); /** * Constructor used by proxy libs */ protected JsfRequestLifecycleBroadcaster() { } @Inject protected JsfRequestLifecycleBroadcaster(Instance<PhaseListener> phaseListenerInstance) { Class phaseListenerClass; for (PhaseListener currentPhaseListener : phaseListenerInstance) { phaseListenerClass = ProxyUtils.getUnproxiedClass(currentPhaseListener.getClass()); if (phaseListenerClass.isAnnotationPresent(JsfPhaseListener.class)) { if (Deactivatable.class.isAssignableFrom(phaseListenerClass) && !ClassDeactivationUtils.isActivated(phaseListenerClass)) { continue; } this.phaseListeners.add(currentPhaseListener); } } //higher ordinals first sortDescending(this.phaseListeners); } private static void sortDescending(List<PhaseListener> phaseListeners) { Collections.sort(phaseListeners, new Comparator<PhaseListener>() { @Override public int compare(PhaseListener phaseListener1, PhaseListener phaseListener2) { return (phaseListener1.getClass().getAnnotation(JsfPhaseListener.class).ordinal() > phaseListener2.getClass().getAnnotation(JsfPhaseListener.class).ordinal()) ? -1 : 1; } }); } protected void broadcastBeforeEvent(PhaseEvent phaseEvent) { //TODO discuss exception handling //fire to phase-observer methods this.phaseEvent.select(createAnnotationLiteral(phaseEvent.getPhaseId(), true)).fire(phaseEvent); this.beforeAnyPhaseEvent.fire(phaseEvent); //fire to ds-phase-listeners for (PhaseListener phaseListener : this.phaseListeners) { PhaseId targetPhase = phaseListener.getPhaseId(); if (targetPhase == PhaseId.ANY_PHASE || targetPhase == phaseEvent.getPhaseId()) { phaseListener.beforePhase(phaseEvent); } } } protected void broadcastAfterEvent(PhaseEvent phaseEvent) { //TODO discuss exception handling //fire to phase-observer methods this.phaseEvent.select(createAnnotationLiteral(phaseEvent.getPhaseId(), false)).fire(phaseEvent); this.afterAnyPhaseEvent.fire(phaseEvent); //fire to ds-phase-listeners //call the listeners in reverse-order (like jsf) ListIterator<PhaseListener> phaseListenerIterator = this.phaseListeners.listIterator(phaseListeners.size()); while (phaseListenerIterator.hasPrevious()) { PhaseListener phaseListener = phaseListenerIterator.previous(); PhaseId targetPhase = phaseListener.getPhaseId(); if (targetPhase == PhaseId.ANY_PHASE || targetPhase == phaseEvent.getPhaseId()) { phaseListener.afterPhase(phaseEvent); } } } protected Annotation createAnnotationLiteral(javax.faces.event.PhaseId phaseId, boolean isBeforeEvent) { if (isBeforeEvent) { return createBeforeLiteral(phaseId); } return createAfterLiteral(phaseId); } protected Annotation createBeforeLiteral(final javax.faces.event.PhaseId phaseId) { return new BeforePhaseBinding() { private static final long serialVersionUID = 749645435335842723L; @Override public JsfPhaseId value() { return JsfPhaseId.convertFromFacesClass(phaseId); } }; } protected Annotation createAfterLiteral(final javax.faces.event.PhaseId phaseId) { return new AfterPhaseBinding() { private static final long serialVersionUID = 390037768660184656L; @Override public JsfPhaseId value() { return JsfPhaseId.convertFromFacesClass(phaseId); } }; } }