org.primefaces.behavior.base.AbstractBehaviorHandler Maven / Gradle / Ivy
/*
* The MIT License
*
* Copyright (c) 2009-2024 PrimeTek Informatics
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package org.primefaces.behavior.base;
import java.beans.BeanDescriptor;
import java.beans.BeanInfo;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.el.ValueExpression;
import javax.faces.application.Application;
import javax.faces.component.UIComponent;
import javax.faces.component.behavior.ClientBehaviorHolder;
import javax.faces.context.FacesContext;
import javax.faces.view.AttachedObjectHandler;
import javax.faces.view.AttachedObjectTarget;
import javax.faces.view.BehaviorHolderAttachedObjectHandler;
import javax.faces.view.BehaviorHolderAttachedObjectTarget;
import javax.faces.view.facelets.*;
import org.primefaces.config.PrimeEnvironment;
import org.primefaces.context.PrimeApplicationContext;
import org.primefaces.util.LangUtils;
public abstract class AbstractBehaviorHandler
extends TagHandler implements BehaviorHolderAttachedObjectHandler {
protected static final String MOJARRA_ATTACHED_OBJECT_HANDLERS_KEY = "javax.faces.view.AttachedObjectHandlers";
protected static final Method MYFACES_GET_COMPOSITION_CONTEXT_INSTANCE;
protected static final Method MYFACES_ADD_ATTACHED_OBJECT_HANDLER;
private static final Logger LOGGER = Logger.getLogger(AbstractBehaviorHandler.class.getName());
private final TagAttribute event;
static {
Class> clazz = LangUtils.tryToLoadClassForName("org.apache.myfaces.view.facelets.FaceletCompositionContext");
if (clazz != null) {
MYFACES_GET_COMPOSITION_CONTEXT_INSTANCE =
LangUtils.tryToLoadMethodForName(clazz, "getCurrentInstance", FaceletContext.class);
MYFACES_ADD_ATTACHED_OBJECT_HANDLER =
LangUtils.tryToLoadMethodForName(clazz, "addAttachedObjectHandler", UIComponent.class, AttachedObjectHandler.class);
}
else {
MYFACES_GET_COMPOSITION_CONTEXT_INSTANCE = null;
MYFACES_ADD_ATTACHED_OBJECT_HANDLER = null;
}
}
protected AbstractBehaviorHandler(TagConfig config) {
super(config);
event = getAttribute("event");
}
@Override
public void apply(FaceletContext faceletContext, UIComponent parent) throws IOException {
if (!ComponentHandler.isNew(parent)) {
return;
}
String eventName = getEventName();
if (UIComponent.isCompositeComponent(parent)) {
boolean tagApplied = false;
if (parent instanceof ClientBehaviorHolder) {
applyAttachedObject(faceletContext, parent);
tagApplied = true;
}
BeanInfo componentBeanInfo = (BeanInfo) parent.getAttributes().get(UIComponent.BEANINFO_KEY);
if (null == componentBeanInfo) {
throw new TagException(tag, "Composite component does not have BeanInfo attribute");
}
BeanDescriptor componentDescriptor = componentBeanInfo.getBeanDescriptor();
if (null == componentDescriptor) {
throw new TagException(tag, "Composite component BeanInfo does not have BeanDescriptor");
}
List targetList = (List) componentDescriptor.getValue(AttachedObjectTarget.ATTACHED_OBJECT_TARGETS_KEY);
if (null == targetList && !tagApplied) {
throw new TagException(tag, "Composite component does not support behavior events");
}
boolean supportedEvent = false;
if (targetList != null) {
for (int i = 0; i < targetList.size(); i++) {
AttachedObjectTarget target = targetList.get(i);
if (target instanceof BehaviorHolderAttachedObjectTarget) {
BehaviorHolderAttachedObjectTarget behaviorTarget = (BehaviorHolderAttachedObjectTarget) target;
if ((null != eventName && eventName.equals(behaviorTarget.getName()))
|| (null == eventName && behaviorTarget.isDefaultEvent())) {
supportedEvent = true;
break;
}
}
}
}
if (supportedEvent) {
// Workaround to implementation specific composite component handlers
FacesContext context = FacesContext.getCurrentInstance();
PrimeEnvironment environment = PrimeApplicationContext.getCurrentInstance(context).getEnvironment();
if (environment.isMojarra()) {
addAttachedObjectHandlerToMojarra(environment, parent);
}
else {
addAttachedObjectHandlerToMyFaces(parent, faceletContext);
}
}
else {
if (!tagApplied) {
throw new TagException(tag, "Composite component does not support event " + eventName);
}
}
}
else if (parent instanceof ClientBehaviorHolder) {
applyAttachedObject(faceletContext, parent);
}
else {
throw new TagException(tag, "Unable to attach behavior to non-ClientBehaviorHolder parent");
}
}
@Override
public String getEventName() {
if (event == null) {
return null;
}
if (event.isLiteral()) {
return event.getValue();
}
else {
FaceletContext faceletContext = getFaceletContext(FacesContext.getCurrentInstance());
ValueExpression expression = event.getValueExpression(faceletContext, String.class);
return (String) expression.getValue(faceletContext);
}
}
protected void setBehaviorAttribute(FaceletContext ctx, E behavior, TagAttribute attr, Class> type) {
if (attr != null) {
String attributeName = attr.getLocalName();
if (attr.isLiteral()) {
behavior.setLiteral(attributeName, attr.getObject(ctx, type));
}
else {
behavior.setValueExpression(attributeName, attr.getValueExpression(ctx, type));
}
}
}
protected FaceletContext getFaceletContext(FacesContext context) {
FaceletContext faceletContext = (FaceletContext) context.getAttributes().get(FaceletContext.FACELET_CONTEXT_KEY);
if (faceletContext == null) {
faceletContext = (FaceletContext) context.getAttributes().get("com.sun.faces.facelets.FACELET_CONTEXT");
}
return faceletContext;
}
@Override
public void applyAttachedObject(FacesContext context, UIComponent parent) {
FaceletContext faceletContext = getFaceletContext(context);
applyAttachedObject(faceletContext, parent);
}
public void applyAttachedObject(FaceletContext faceletContext, UIComponent parent) {
ClientBehaviorHolder holder = (ClientBehaviorHolder) parent;
String eventName = getEventName();
if (null == eventName) {
eventName = holder.getDefaultEventName();
if (null == eventName) {
throw new TagException(tag, "Event attribute could not be determined: " + eventName);
}
}
else {
Collection eventNames = holder.getEventNames();
if (!eventNames.contains(eventName)) {
throw new TagException(tag, "Event:" + eventName + " is not supported.");
}
}
Application application = faceletContext.getFacesContext().getApplication();
E behavior = (E) application.createBehavior(getBehaviorId());
init(faceletContext, behavior, eventName, parent);
holder.addClientBehavior(eventName, behavior);
}
public abstract String getBehaviorId();
@Override
public String getFor() {
return null;
}
protected void addAttachedObjectHandlerToMojarra(PrimeEnvironment environment, UIComponent component) {
Map attrs = component.getAttributes();
List result = (List) attrs.computeIfAbsent(MOJARRA_ATTACHED_OBJECT_HANDLERS_KEY,
k -> new ArrayList(5));
result.add(this);
}
protected void addAttachedObjectHandlerToMyFaces(UIComponent component, FaceletContext ctx) {
try {
Object faceletCompositionContextInstance = MYFACES_GET_COMPOSITION_CONTEXT_INSTANCE.invoke(null, ctx);
MYFACES_ADD_ATTACHED_OBJECT_HANDLER.invoke(faceletCompositionContextInstance, component, this);
}
catch (Exception ex) {
LOGGER.log(Level.SEVERE, "Could not add AttachedObjectHandler to MyFaces!", ex);
}
}
protected void init(FaceletContext ctx, E behavior, String eventName, UIComponent parent) {
for (BehaviorAttribute attr : behavior.getAllAttributes()) {
TagAttribute tag = getAttribute(attr.getName());
setBehaviorAttribute(ctx, behavior, tag, attr.getExpectedType());
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy