001: /*
002: * Copyright 2004 The Apache Software Foundation.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016: package org.apache.myfaces.taglib.core;
017:
018: import org.apache.commons.logging.Log;
019: import org.apache.commons.logging.LogFactory;
020: import org.apache.myfaces.shared_impl.util.ClassUtils;
021:
022: import javax.el.ValueExpression;
023: import javax.faces.FacesException;
024: import javax.faces.component.UIViewRoot;
025: import javax.faces.context.FacesContext;
026: import javax.faces.event.AbortProcessingException;
027: import javax.faces.event.PhaseEvent;
028: import javax.faces.event.PhaseId;
029: import javax.faces.event.PhaseListener;
030: import javax.faces.webapp.UIComponentELTag;
031: import javax.servlet.jsp.JspException;
032: import javax.servlet.jsp.tagext.Tag;
033: import javax.servlet.jsp.tagext.TagSupport;
034: import java.io.Serializable;
035:
036: /**
037: * @author martin.haimberger
038: * @version $Revision: 462929 $ $Date: 2006-10-11 21:26:36 +0100 (mié, 11 oct 2006) $
039: */
040: public class PhaseListenerTag extends TagSupport {
041:
042: private final Log log = LogFactory.getLog(PhaseListenerTag.class);
043:
044: /**
045: * The fully qualified class name of the PhaseListener which should be created.
046: */
047: private ValueExpression type = null;
048:
049: /**
050: * A value binding expression used to create a PhaseListener instance.
051: */
052: private ValueExpression binding = null;
053:
054: /*--- Setter ---*/
055: public void setType(ValueExpression type) {
056: this .type = type;
057: }
058:
059: public void setBinding(ValueExpression binding) {
060: this .binding = binding;
061: }
062:
063: public int doStartTag() throws JspException {
064:
065: // JSF-Spec 1.2 9.4.9
066: // Locate the one and only UIViewRoot custom action instance by walking up the tag tree
067: // until you find a UIComponentELTag instance that has no parent. If the
068: // getCreated() method of this instance returns true, check the binding attribute.
069:
070: Tag parent = this ;
071: UIComponentELTag parentTag = null;
072: while ((parent = parent.getParent()) != null) {
073: if (parent instanceof UIComponentELTag) {
074: parentTag = (UIComponentELTag) parent;
075: }
076: }
077:
078: if (parentTag == null) {
079: throw new JspException(
080: "Not nested in a UIViewRoot Error for tag with handler class: "
081: + this .getClass().getName());
082: }
083:
084: if (!parentTag.getCreated()) {
085: return SKIP_BODY;
086: }
087:
088: UIViewRoot root = (UIViewRoot) parentTag.getComponentInstance();
089:
090: // JSF-Spec 1.2 9.4.9
091: // If binding is set, call binding.getValue() to obtain a reference to the
092: // PhaseListener instance. If there is no exception thrown, and binding.getValue()
093: // returned a non-null object that implements javax.faces.event.PhaseListener, register
094: // it by calling addPhaseListener(). If there was an exception thrown, rethrow the
095: // exception as a JspException.
096:
097: // If the listener instance could not be created, check the type attribute. If the type
098: // attribute is set, instantiate an instance of the specified class, and register it by calling
099: // addPhaseListener(). If the binding attribute was also set, store the listener instance
100: // by calling binding.setValue(). If there was an exception thrown, rethrow the
101: // exception as a JspException.
102:
103: PhaseListener listener = null;
104: try {
105: listener = new BindingPhaseListener(binding, type);
106: } catch (Exception ex) {
107: throw new JspException(ex.getMessage(), ex);
108: }
109:
110: root.addPhaseListener(listener);
111:
112: return SKIP_BODY;
113:
114: }
115:
116: private static class BindingPhaseListener implements PhaseListener,
117: Serializable {
118:
119: private transient PhaseListener phaseListenerCache = null;
120: private ValueExpression type;
121: private ValueExpression binding;
122: private final Log log = LogFactory
123: .getLog(PhaseListenerTag.class);
124:
125: BindingPhaseListener(ValueExpression binding,
126: ValueExpression type) {
127: this .binding = binding;
128: this .type = type;
129: }
130:
131: public void afterPhase(PhaseEvent event) {
132: PhaseListener listener = getPhaseListener();
133: if (listener != null) {
134: listener.afterPhase(event);
135: }
136: }
137:
138: public void beforePhase(PhaseEvent event) {
139: PhaseListener listener = getPhaseListener();
140: if (listener != null) {
141: listener.beforePhase(event);
142: }
143: }
144:
145: public PhaseId getPhaseId() {
146: PhaseListener listener = getPhaseListener();
147: if (listener != null) {
148: return listener.getPhaseId();
149: }
150:
151: return null;
152:
153: }
154:
155: private PhaseListener getPhaseListener() {
156:
157: if (phaseListenerCache != null) {
158: return phaseListenerCache;
159: } else {
160: // create PhaseListenerInstance
161: phaseListenerCache = getPhaseListnerInstance(binding,
162: type);
163: }
164: if (phaseListenerCache == null) {
165: log
166: .warn("PhaseListener will not be installed. Both binding and type are null.");
167:
168: }
169:
170: return phaseListenerCache;
171:
172: }
173:
174: private PhaseListener getPhaseListnerInstance(
175: ValueExpression binding, ValueExpression type) {
176: FacesContext currentFacesContext = FacesContext
177: .getCurrentInstance();
178: Object phasesInstance = null;
179: if (binding != null) {
180: phasesInstance = binding.getValue(currentFacesContext
181: .getELContext());
182: } else if (type != null) {
183: try {
184: phasesInstance = ClassUtils
185: .newInstance((String) type
186: .getValue(currentFacesContext
187: .getELContext()));
188: } catch (FacesException ex) {
189: throw new AbortProcessingException(ex.getMessage(),
190: ex);
191: }
192: }
193: return (PhaseListener) phasesInstance;
194:
195: }
196:
197: }
198: }
|