View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.myfaces.taglib.core;
20  
21  import javax.el.ELException;
22  import javax.el.ValueExpression;
23  import javax.faces.component.UIComponent;
24  import javax.faces.context.FacesContext;
25  import javax.faces.webapp.UIComponentClassicTagBase;
26  import javax.faces.webapp.UIComponentELTag;
27  import javax.servlet.jsp.JspException;
28  import javax.servlet.jsp.tagext.Tag;
29  import javax.servlet.jsp.tagext.TagSupport;
30  
31  import org.apache.myfaces.shared.util.ClassUtils;
32  
33  /**
34   * @author Andreas Berger (latest modification by $Author$)
35   * @version $Revision$ $Date$
36   * @since 1.2
37   */
38  public abstract class GenericListenerTag<_Holder, _Listener> extends TagSupport
39  {
40      private ValueExpression _type = null;
41      private ValueExpression _binding = null;
42      private Class<_Holder> _holderClazz;
43  
44      protected GenericListenerTag(Class<_Holder> holderClazz)
45      {
46          super();
47          _holderClazz = holderClazz;
48      }
49  
50      public void setType(ValueExpression type)
51      {
52          _type = type;
53      }
54  
55      public void setBinding(ValueExpression binding)
56      {
57          _binding = binding;
58      }
59  
60      @Override
61      public void release()
62      {
63          super.release();
64          _type = null;
65          _binding = null;
66      }
67  
68      protected abstract void addListener(_Holder holder, _Listener listener);
69  
70      protected abstract _Listener createDelegateListener(ValueExpression type, ValueExpression binding);
71  
72      @Override
73      @SuppressWarnings("unchecked")
74      public int doStartTag() throws JspException
75      {
76          UIComponentClassicTagBase componentTag = UIComponentELTag.getParentUIComponentClassicTagBase(pageContext);
77          if (componentTag == null)
78          {
79              throw new JspException("no parent UIComponentTag found");
80          }
81  
82          if (_type == null && _binding == null)
83          {
84              throw new JspException("\"actionListener\" must have binding and/or type attribute.");
85          }
86  
87          if (!componentTag.getCreated())
88          {
89              return Tag.SKIP_BODY;
90          }
91  
92          _Holder holder = null;
93          UIComponent component = componentTag.getComponentInstance();
94          try
95          {
96              holder = (_Holder)component;
97          }
98          catch (ClassCastException e)
99          {
100             throw new JspException("Component " + ((UIComponent)holder).getId() + " is not instance of "
101                     + _holderClazz.getName());
102         }
103 
104         if (_type != null && _type.isLiteralText())
105         {
106             createListener(holder, component);
107         }
108         else
109         {
110             addListener(holder, createDelegateListener(_type, _binding));
111         }
112 
113         return Tag.SKIP_BODY;
114     }
115 
116     @SuppressWarnings("unchecked")
117     protected void createListener(_Holder holder, UIComponent component) throws JspException
118     {
119         FacesContext facesContext = FacesContext.getCurrentInstance();
120         _Listener listener;
121         // type and/or binding must be specified
122         try
123         {
124             if (null != _binding)
125             {
126                 try
127                 {
128                     listener = (_Listener)_binding.getValue(facesContext.getELContext());
129                     if (null != listener)
130                     {
131                         addListener(holder, listener);
132                         // no need for further processing
133                         return;
134                     }
135                 }
136                 catch (ELException e)
137                 {
138                     throw new JspException("Exception while evaluating the binding attribute of Component "
139                             + component.getId(), e);
140                 }
141             }
142             if (null != _type)
143             {
144                 String className;
145                 if (_type.isLiteralText())
146                 {
147                     className = _type.getExpressionString();
148                     // If type is literal text we should create
149                     // a new instance
150                     listener = (_Listener)ClassUtils.newInstance(className);
151                 }
152                 else
153                 {
154                     className = (String)_type.getValue(facesContext.getELContext());
155                     listener = null;
156                 }
157 
158                 if (null != _binding)
159                 {
160                     try
161                     {
162                         _binding.setValue(facesContext.getELContext(), listener);
163                     }
164                     catch (ELException e)
165                     {
166                         throw new JspException("Exception while evaluating the binding attribute of Component "
167                                 + component.getId(), e);
168                     }
169                 }
170                 else
171                 {
172                     // Type is a EL expression, and there is
173                     // no binding property so we should create
174                     // a new instance
175                     listener = (_Listener)ClassUtils.newInstance(className);
176                 }
177                 addListener(holder, listener);
178             }
179         }
180         catch (ClassCastException e)
181         {
182             throw new JspException(e);
183         }
184     }
185 
186 }