All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.sun.faces.facelets.tag.jsf.core.AjaxHandler Maven / Gradle / Ivy

Go to download

This is the master POM file for Oracle's Implementation of the JSF 2.2 Specification.

The newest version!
/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * Copyright (c) 1997-2011 Oracle and/or its affiliates. All rights reserved.
 *
 * The contents of this file are subject to the terms of either the GNU
 * General Public License Version 2 only ("GPL") or the Common Development
 * and Distribution License("CDDL") (collectively, the "License").  You
 * may not use this file except in compliance with the License.  You can
 * obtain a copy of the License at
 * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
 * or packager/legal/LICENSE.txt.  See the License for the specific
 * language governing permissions and limitations under the License.
 *
 * When distributing the software, include this License Header Notice in each
 * file and include the License file at packager/legal/LICENSE.txt.
 *
 * GPL Classpath Exception:
 * Oracle designates this particular file as subject to the "Classpath"
 * exception as provided by Oracle in the GPL Version 2 section of the License
 * file that accompanied this code.
 *
 * Modifications:
 * If applicable, add the following below the License Header, with the fields
 * enclosed by brackets [] replaced by your own identifying information:
 * "Portions Copyright [year] [name of copyright owner]"
 *
 * Contributor(s):
 * If you wish your version of this file to be governed by only the CDDL or
 * only the GPL Version 2, indicate your decision by adding "[Contributor]
 * elects to include this software in this distribution under the [CDDL or GPL
 * Version 2] license."  If you don't indicate a single choice of license, a
 * recipient has the option to distribute your version of this file under
 * either the CDDL, the GPL Version 2 or to extend the choice of license to
 * its licensees as provided above.  However, if you add GPL Version 2 code
 * and therefore, elected the GPL Version 2 license, then the option applies
 * only if the new code is made subject to such option by the copyright
 * holder.
 *
 *
 * This file incorporates work covered by the following copyright and
 * permission notice:
 *
 * Copyright 2005-2007 The Apache Software Foundation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.sun.faces.facelets.tag.jsf.core;

import com.sun.faces.renderkit.RenderKitUtils;
import com.sun.faces.component.behavior.AjaxBehaviors;
import com.sun.faces.facelets.tag.TagHandlerImpl;
import com.sun.faces.facelets.tag.jsf.CompositeComponentTagHandler;

import javax.el.ELContext;
import javax.el.MethodExpression;
import javax.el.MethodNotFoundException;
import javax.faces.application.Application;
import javax.faces.component.UIComponent;
import javax.faces.component.UIOutput;
import javax.faces.component.behavior.AjaxBehavior;
import javax.faces.component.behavior.ClientBehaviorHolder;
import javax.faces.context.FacesContext;
import javax.faces.event.AbortProcessingException;
import javax.faces.event.AjaxBehaviorEvent;
import javax.faces.event.AjaxBehaviorListener;
import javax.faces.view.AttachedObjectTarget;
import javax.faces.view.BehaviorHolderAttachedObjectHandler;
import javax.faces.view.BehaviorHolderAttachedObjectTarget;
import javax.faces.view.facelets.*;
import java.beans.BeanDescriptor;
import java.beans.BeanInfo;
import java.io.IOException;
import java.io.Serializable;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.TreeSet;



/**
 * 

Enable * one or more components in the view * to perform Ajax operations. This tag handler must create an instance * of {@link javax.faces.component.behavior.AjaxBehavior} using the tag attribute * values.

The events attribute for * this tag that can be a ValueExpression must be evaluated at tag * execution time since the event name is used in the process of Behavior * creation.
If this tag is nested within a single * {@link ClientBehaviorHolder} component: *
    *
  • If the events attribute value is not specified, * obtain the default event name by calling {@link ClientBehaviorHolder#getDefaultEventName}. * If that returns null throw an exception.
  • *
  • If the events attribute value is specified, ensure it * that it exists in the Collection returned from a call to * {@link ClientBehaviorHolder#getEventNames} and throw an exception if * it doesn't exist.
  • *
  • Add the {@link AjaxBehavior} instance to the {@link ClientBehaviorHolder} * component by calling {@link ClientBehaviorHolder#addClientBehavior} passing event * and the {@link AjaxBehavior} instance.
  • *
*

* Check for the existence of the Ajax resource by calling * UIViewRoot.getComponentResources(). If * the Ajax resource does not exist, create a UIOutput component * instance and set the renderer type to javax.faces.resource.Script. * Set the the following attributes in the component's attribute Map: * library with the value javax.faces and * name with the value jsf.js. Install the component * resource using UIViewRoot.addComponentResource() and specifying * head as the target argument.

* * If this tag has component children, add the {@link AjaxBehavior} to * {@link AjaxBehaviors} by calling {@link AjaxBehaviors#pushBehavior}. As * subsequent child components that implement the {@link ClientBehaviorHolder} interface * are evaluated this {@link AjaxBehavior} instance must be added as a behavior to * the component. *

* @version $Id: AjaxHandler.java 5369 2008-09-08 19:53:45Z rogerk $ */ public final class AjaxHandler extends TagHandlerImpl implements BehaviorHolderAttachedObjectHandler { private final TagAttribute event; private final TagAttribute execute; private final TagAttribute render; private final TagAttribute onevent; private final TagAttribute onerror; private final TagAttribute disabled; private final TagAttribute immediate; private final TagAttribute resetValues; private final TagAttribute listener; private final TagAttribute delay; private final boolean wrapping; /** * @param config */ public AjaxHandler(TagConfig config) { super(config); this.event = this.getAttribute("event"); this.execute = this.getAttribute("execute"); this.render = this.getAttribute("render"); this.onevent = this.getAttribute("onevent"); this.onerror = this.getAttribute("onerror"); this.disabled = this.getAttribute("disabled"); this.immediate = this.getAttribute("immediate"); this.resetValues = this.getAttribute("resetValues"); this.listener = this.getAttribute("listener"); this.delay = this.getAttribute("delay"); this.wrapping = isWrapping(); } /* * (non-Javadoc) * * @see com.sun.facelets.FaceletHandler#apply(com.sun.facelets.FaceletContext, * javax.faces.component.UIComponent) */ public void apply(FaceletContext ctx, UIComponent parent) throws IOException { String eventName = getEventName(); if (this.wrapping) { applyWrapping(ctx, parent, eventName); } else { applyNested(ctx, parent, eventName); } } public void applyAttachedObject(FacesContext context, UIComponent parent) { FaceletContext ctx = (FaceletContext) context.getAttributes().get(FaceletContext.FACELET_CONTEXT_KEY); applyAttachedObject(ctx, parent, getEventName()); } /* (non-Javadoc) * @see javax.faces.view.AttachedObjectHandler#getFor() */ public String getFor() { return null; } /* (non-Javadoc) * @see javax.faces.view.BehaviorHolderAttachedObjectHandler#getEventName() */ public String getEventName() { FacesContext context = FacesContext.getCurrentInstance(); FaceletContext ctx = (FaceletContext) context.getAttributes().get(FaceletContext.FACELET_CONTEXT_KEY); return (this.event != null) ? this.event.getValue(ctx) : null; } // Tests whether the is wrapping other tags. private boolean isWrapping() { // Would be nice if there was some easy way to determine whether // we are a leaf handler. However, even leaf handlers have a // non-null nextHandler - the CompilationUnit.LEAF instance. // We assume that if we've got a TagHandler or CompositeFaceletHandler // as our nextHandler, we are not a leaf. return ((this.nextHandler instanceof TagHandler) || (this.nextHandler instanceof CompositeFaceletHandler)); } // Applies a wrapping AjaxHandler by pushing/popping the AjaxBehavior // to the AjaxBeahviors object. private void applyWrapping(FaceletContext ctx, UIComponent parent, String eventName) throws IOException { // In the wrapping case, we assume that some wrapped component // is going to be Ajax enabled and install the Ajax resource. installAjaxResourceIfNecessary(); AjaxBehavior ajaxBehavior = createAjaxBehavior(ctx, eventName); // We leverage AjaxBehaviors to support the wrapping case. We // push/pop the AjaxBehavior instance on AjaxBehaviors so that // child tags will have access to it. FacesContext context = ctx.getFacesContext(); AjaxBehaviors ajaxBehaviors = AjaxBehaviors.getAjaxBehaviors(context, true); ajaxBehaviors.pushBehavior(context, ajaxBehavior, eventName); nextHandler.apply(ctx, parent); ajaxBehaviors.popBehavior(); } // Applies a nested AjaxHandler by adding the AjaxBehavior to the // parent component. private void applyNested(FaceletContext ctx, UIComponent parent, String eventName) { if (!ComponentHandler.isNew(parent)) { return; } // Composite component case if (UIComponent.isCompositeComponent(parent)) { // Check composite component event name: boolean tagApplied = false; if (parent instanceof ClientBehaviorHolder) { applyAttachedObject(ctx, parent, eventName); // error here will propagate up tagApplied = true; } BeanInfo componentBeanInfo = (BeanInfo) parent.getAttributes().get( UIComponent.BEANINFO_KEY); if (null == componentBeanInfo) { throw new TagException( tag, "Error: enclosing composite component does not have BeanInfo attribute"); } BeanDescriptor componentDescriptor = componentBeanInfo.getBeanDescriptor(); if (null == componentDescriptor) { throw new TagException( tag, "Error: enclosing 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, "Error: enclosing composite component does not support behavior events"); } boolean supportedEvent = false; for (AttachedObjectTarget target : targetList) { if (target instanceof BehaviorHolderAttachedObjectTarget) { BehaviorHolderAttachedObjectTarget behaviorTarget = (BehaviorHolderAttachedObjectTarget) target; if ((null != eventName && eventName.equals(behaviorTarget.getName())) || (null == eventName && behaviorTarget.isDefaultEvent())) { supportedEvent = true; break; } } } if (supportedEvent) { CompositeComponentTagHandler.getAttachedObjectHandlers(parent) .add(this); } else { if (!tagApplied) { throw new TagException( tag, "Error: enclosing composite component does not support event " + eventName); } } } else if (parent instanceof ClientBehaviorHolder) { applyAttachedObject(ctx, parent, eventName); } else { throw new TagException(this.tag, "Unable to attach to non-ClientBehaviorHolder parent"); } } /** *

* @param ctx * @param parent * @param eventName */ private void applyAttachedObject(FaceletContext ctx, UIComponent parent, String eventName) { ClientBehaviorHolder bHolder = (ClientBehaviorHolder) parent; if (null == eventName) { eventName = bHolder.getDefaultEventName(); if (null == eventName) { throw new TagException(this.tag, "Event attribute could not be determined: " + eventName); } } else { Collection eventNames = bHolder.getEventNames(); if (!eventNames.contains(eventName)) { throw new TagException(this.tag, getUnsupportedEventMessage(eventName, eventNames, parent)); } } AjaxBehavior ajaxBehavior = createAjaxBehavior(ctx, eventName); bHolder.addClientBehavior(eventName, ajaxBehavior); installAjaxResourceIfNecessary(); } // Construct our AjaxBehavior from tag parameters. private AjaxBehavior createAjaxBehavior(FaceletContext ctx, String eventName) { Application application = ctx.getFacesContext().getApplication(); AjaxBehavior behavior = (AjaxBehavior)application.createBehavior( AjaxBehavior.BEHAVIOR_ID); setBehaviorAttribute(ctx, behavior, this.onevent, String.class); setBehaviorAttribute(ctx, behavior, this.onerror, String.class); setBehaviorAttribute(ctx, behavior, this.disabled, Boolean.class); setBehaviorAttribute(ctx, behavior, this.immediate, Boolean.class); setBehaviorAttribute(ctx, behavior, this.resetValues, Boolean.class); setBehaviorAttribute(ctx, behavior, this.execute, Object.class); setBehaviorAttribute(ctx, behavior, this.render, Object.class); setBehaviorAttribute(ctx, behavior, this.delay, String.class); if (null != listener) { behavior.addAjaxBehaviorListener(new AjaxBehaviorListenerImpl( this.listener.getMethodExpression(ctx, Object.class, new Class[] { AjaxBehaviorEvent.class }), this.listener.getMethodExpression(ctx, Object.class, new Class[] { }))); } return behavior; } // Sets the value from the TagAttribute on the behavior private void setBehaviorAttribute(FaceletContext ctx, AjaxBehavior behavior, TagAttribute attr, Class type) { if (attr != null) { behavior.setValueExpression(attr.getLocalName(), attr.getValueExpression(ctx, type)); } } // Only install the Ajax resource if it doesn't exist. // The resource component will be installed with the target "head". // private void installAjaxResourceIfNecessary() { FacesContext context = FacesContext.getCurrentInstance(); if (RenderKitUtils.hasScriptBeenRendered(context)) { // Already included, return return; } final String name = "jsf.js"; final String library = "javax.faces"; if (RenderKitUtils.hasResourceBeenInstalled(context, name, library)) { RenderKitUtils.setScriptAsRendered(context); return; } UIOutput output = new UIOutput(); output.setRendererType("javax.faces.resource.Script"); output.getAttributes().put("name", name); output.getAttributes().put("library", library); context.getViewRoot().addComponentResource(context, output, "head"); // Set the context to record script as included RenderKitUtils.setScriptAsRendered(context); } // Returns an error message for the case where the event // attribute specified an unknown/unsupported event. private String getUnsupportedEventMessage(String eventName, Collection eventNames, UIComponent parent) { StringBuilder builder = new StringBuilder(100); builder.append("'"); builder.append(eventName); builder.append("' is not a supported event for "); builder.append(parent.getClass().getSimpleName()); builder.append(". Please specify one of these supported event names: "); // Might as well sort the event names for a cleaner error message. Collection sortedEventNames = new TreeSet(eventNames); Iterator iter = sortedEventNames.iterator(); boolean hasNext = iter.hasNext(); while (hasNext) { builder.append(iter.next()); hasNext = iter.hasNext(); if (hasNext) { builder.append(", "); } } builder.append("."); return builder.toString(); } } class AjaxBehaviorListenerImpl implements AjaxBehaviorListener, Serializable { private static final long serialVersionUID = -6056525197409773897L; private MethodExpression oneArgListener; private MethodExpression noArgListener; // Necessary for state saving public AjaxBehaviorListenerImpl() {} public AjaxBehaviorListenerImpl(MethodExpression oneArg, MethodExpression noArg) { this.oneArgListener = oneArg; this.noArgListener = noArg; } public void processAjaxBehavior(AjaxBehaviorEvent event) throws AbortProcessingException { final ELContext elContext = FacesContext.getCurrentInstance().getELContext(); try{ noArgListener.invoke(elContext, new Object[]{}); } catch (MethodNotFoundException mnfe) { // Attempt to call public void method(AjaxBehaviorEvent event) oneArgListener.invoke(elContext, new Object[]{event}); } catch (IllegalArgumentException iae) { // Attempt to call public void method(AjaxBehaviorEvent event) oneArgListener.invoke(elContext, new Object[]{event}); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy