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.commons.logging.Log; 028 import org.apache.commons.logging.LogFactory; 029 030 import javax.faces.component.UIComponent; 031 import javax.faces.context.FacesContext; 032 import javax.faces.el.ValueBinding; 033 import javax.faces.webapp.UIComponentTag; 034 import javax.servlet.jsp.JspException; 035 import javax.servlet.jsp.tagext.TagSupport; 036 037 /** 038 * Register an TabChangedListener instance on the UIComponent 039 * associated with the closest parent UIComponent custom action. 040 */ 041 @Tag(name = "tabChangeListener", bodyContent = BodyContent.EMPTY) 042 public class TabChangeListenerTag extends TagSupport { 043 044 private static final Log LOG = LogFactory.getLog(TabChangeListenerTag.class); 045 /** 046 * <p>The fully qualified class name of the {@link TabChangeListener} 047 * instance to be created.</p> 048 */ 049 private String type; 050 private String binding; 051 /** 052 * Fully qualified Java class name of a TabChangeListener to be 053 * created and registered. 054 */ 055 @TagAttribute(required = true) 056 public void setType(String type) { 057 this.type = type; 058 } 059 060 /** 061 * The value binding expression to a TabChangeListener. 062 */ 063 @TagAttribute 064 public void setBinding(String binding) { 065 this.binding = binding; 066 } 067 068 069 070 /** 071 * <p>Create a new instance of the specified {@link TabChangeListener} 072 * class, and register it with the {@link javax.faces.component.UIComponent} instance associated 073 * with our most immediately surrounding {@link javax.faces.webapp.UIComponentTag} instance, if 074 * the {@link javax.faces.component.UIComponent} instance was created by this execution of the 075 * containing JSP page.</p> 076 * 077 * @throws JspException if a JSP error occurs 078 */ 079 public int doStartTag() throws JspException { 080 081 // Locate our parent UIComponentTag 082 UIComponentTag tag = 083 UIComponentTag.getParentUIComponentTag(pageContext); 084 if (tag == null) { 085 // TODO Message resource i18n 086 throw new JspException("Not nested in faces tag"); 087 } 088 089 if (!tag.getCreated()) { 090 return (SKIP_BODY); 091 } 092 093 UIComponent component = tag.getComponentInstance(); 094 if (component == null) { 095 // TODO Message resource i18n 096 throw new JspException("Component Instance is null"); 097 } 098 if (!(component instanceof TabChangeSource)) { 099 // TODO Message resource i18n 100 throw new JspException("Component "+ component.getClass().getName() + " is not instanceof TabChangeSource"); 101 } 102 TabChangeSource changeSource = (TabChangeSource) component; 103 104 TabChangeListener handler = null; 105 ValueBinding valueBinding = null; 106 if (binding != null && UIComponentTag.isValueReference(binding)) { 107 valueBinding = ComponentUtil.createValueBinding(binding); 108 if (valueBinding != null) { 109 Object obj = valueBinding.getValue(FacesContext.getCurrentInstance()); 110 if (obj != null && obj instanceof TabChangeListener) { 111 handler = (TabChangeListener) obj; 112 } 113 } 114 } 115 116 if (handler == null && type != null) { 117 handler = createTabChangeListener(type); 118 if (handler != null && valueBinding != null) { 119 valueBinding.setValue(FacesContext.getCurrentInstance(), handler); 120 } 121 } 122 if (handler != null) { 123 if (valueBinding != null) { 124 changeSource.addTabChangeListener(new TabChangeListenerValueBindingDelegate(type, valueBinding)); 125 } else { 126 changeSource.addTabChangeListener(handler); 127 } 128 } 129 // TODO else LOG.warn? 130 return (SKIP_BODY); 131 } 132 133 134 /** 135 * <p>Release references to any acquired resources. 136 */ 137 public void release() { 138 this.type = null; 139 this.binding = null; 140 } 141 142 /** 143 * <p>Create and return a new {@link TabChangeListener} to be registered 144 * on our surrounding {@link javax.faces.component.UIComponent}.</p> 145 * 146 * @throws javax.servlet.jsp.JspException if a new instance cannot be created 147 */ 148 protected TabChangeListener createTabChangeListener(String className) throws JspException { 149 try { 150 Class clazz = getClass().getClassLoader().loadClass(className); 151 return ((TabChangeListener) clazz.newInstance()); 152 } catch (Exception e) { 153 throw new JspException(e); 154 } 155 } 156 }