001 package org.apache.myfaces.tobago.taglib.component; 002 003 /* 004 * Licensed to the Apache Software Foundation (ASF) under one or more 005 * contributor license agreements. See the NOTICE file distributed with 006 * this work for additional information regarding copyright ownership. 007 * The ASF licenses this file to You under the Apache License, Version 2.0 008 * (the "License"); you may not use this file except in compliance with 009 * the License. You may obtain a copy of the License at 010 * 011 * http://www.apache.org/licenses/LICENSE-2.0 012 * 013 * Unless required by applicable law or agreed to in writing, software 014 * distributed under the License is distributed on an "AS IS" BASIS, 015 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 016 * See the License for the specific language governing permissions and 017 * limitations under the License. 018 */ 019 020 import org.apache.myfaces.tobago.apt.annotation.BodyContent; 021 import org.apache.myfaces.tobago.apt.annotation.Tag; 022 import org.apache.myfaces.tobago.apt.annotation.TagAttribute; 023 import org.apache.myfaces.tobago.component.ComponentUtil; 024 import org.apache.myfaces.tobago.event.TabChangeListener; 025 import org.apache.myfaces.tobago.event.TabChangeSource; 026 import org.apache.myfaces.tobago.event.TabChangeListenerValueBindingDelegate; 027 import org.apache.myfaces.tobago.event.TabChangeEvent; 028 029 import org.apache.commons.logging.Log; 030 import org.apache.commons.logging.LogFactory; 031 032 import javax.faces.component.UIComponent; 033 import javax.faces.context.FacesContext; 034 import javax.faces.el.ValueBinding; 035 import javax.faces.el.MethodBinding; 036 import javax.faces.webapp.UIComponentTag; 037 import javax.faces.application.Application; 038 import javax.servlet.jsp.JspException; 039 import javax.servlet.jsp.tagext.TagSupport; 040 041 /** 042 * Register an TabChangedListener instance on the UIComponent 043 * associated with the closest parent UIComponent custom action. 044 */ 045 @Tag(name = "tabChangeListener", bodyContent = BodyContent.EMPTY) 046 public class TabChangeListenerTag extends TagSupport { 047 048 private static final long serialVersionUID = -419199086962377873L; 049 050 private static final Class[] TAB_CHANGE_LISTENER_ARGS = new Class[] {TabChangeEvent.class}; 051 052 private static final Log LOG = LogFactory.getLog(TabChangeListenerTag.class); 053 054 /** 055 * <p>The fully qualified class name of the {@link TabChangeListener} 056 * instance to be created.</p> 057 */ 058 private String type; 059 private String binding; 060 private String listener; 061 062 /** 063 * Fully qualified Java class name of a TabChangeListener to be 064 * created and registered. 065 */ 066 @TagAttribute(required = true) 067 public void setType(String type) { 068 this.type = type; 069 } 070 071 /** 072 * The value binding expression to a TabChangeListener. 073 */ 074 @TagAttribute 075 public void setBinding(String binding) { 076 this.binding = binding; 077 } 078 079 080 /** 081 * A method binding expression to a processTabChange(TabChangeEvent tabChangeEvent) method. 082 */ 083 @TagAttribute 084 public void setListener(String listener) { 085 this.listener = listener; 086 } 087 088 /** 089 * <p>Create a new instance of the specified {@link TabChangeListener} 090 * class, and register it with the {@link javax.faces.component.UIComponent} instance associated 091 * with our most immediately surrounding {@link javax.faces.webapp.UIComponentTag} instance, if 092 * the {@link javax.faces.component.UIComponent} instance was created by this execution of the 093 * containing JSP page.</p> 094 * 095 * @throws JspException if a JSP error occurs 096 */ 097 public int doStartTag() throws JspException { 098 099 // Locate our parent UIComponentTag 100 UIComponentTag tag = 101 UIComponentTag.getParentUIComponentTag(pageContext); 102 if (tag == null) { 103 // TODO Message resource i18n 104 throw new JspException("Not nested in faces tag"); 105 } 106 107 if (!tag.getCreated()) { 108 return (SKIP_BODY); 109 } 110 111 UIComponent component = tag.getComponentInstance(); 112 if (component == null) { 113 // TODO Message resource i18n 114 throw new JspException("Component Instance is null"); 115 } 116 if (!(component instanceof TabChangeSource)) { 117 // TODO Message resource i18n 118 throw new JspException("Component " + component.getClass().getName() + " is not instanceof TabChangeSource"); 119 } 120 TabChangeSource changeSource = (TabChangeSource) component; 121 122 TabChangeListener handler = null; 123 ValueBinding valueBinding = null; 124 if (binding != null && UIComponentTag.isValueReference(binding)) { 125 valueBinding = ComponentUtil.createValueBinding(binding); 126 if (valueBinding != null) { 127 Object obj = valueBinding.getValue(FacesContext.getCurrentInstance()); 128 if (obj != null && obj instanceof TabChangeListener) { 129 handler = (TabChangeListener) obj; 130 } 131 } 132 } 133 134 if (handler == null && type != null) { 135 handler = createTabChangeListener(type); 136 if (handler != null && valueBinding != null) { 137 valueBinding.setValue(FacesContext.getCurrentInstance(), handler); 138 } 139 } 140 if (handler != null) { 141 if (valueBinding != null) { 142 changeSource.addTabChangeListener(new TabChangeListenerValueBindingDelegate(type, valueBinding)); 143 } else { 144 changeSource.addTabChangeListener(handler); 145 } 146 } 147 148 if (listener != null && UIComponentTag.isValueReference(listener)) { 149 Application application = FacesContext.getCurrentInstance().getApplication(); 150 MethodBinding methodBinding = application.createMethodBinding(listener, TAB_CHANGE_LISTENER_ARGS); 151 changeSource.setTabChangeListener(methodBinding); 152 } 153 // TODO else LOG.warn? 154 return (SKIP_BODY); 155 } 156 157 158 /** 159 * <p>Release references to any acquired resources. 160 */ 161 public void release() { 162 this.type = null; 163 this.binding = null; 164 } 165 166 /** 167 * <p>Create and return a new {@link TabChangeListener} to be registered 168 * on our surrounding {@link javax.faces.component.UIComponent}.</p> 169 * 170 * @throws javax.servlet.jsp.JspException if a new instance cannot be created 171 */ 172 protected TabChangeListener createTabChangeListener(String className) throws JspException { 173 try { 174 Class clazz = getClass().getClassLoader().loadClass(className); 175 return ((TabChangeListener) clazz.newInstance()); 176 } catch (Exception e) { 177 throw new JspException(e); 178 } 179 } 180 }