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

com.sun.faces.application.ApplicationImpl Maven / Gradle / Ivy

/*
 * 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.
 */

package com.sun.faces.application;

import com.sun.faces.spi.InjectionProviderException;

import java.beans.*;
import java.lang.reflect.Constructor;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Locale;
import java.util.Map;
import java.util.ResourceBundle;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.el.CompositeELResolver;
import javax.el.ELContextListener;
import javax.el.ELException;
import javax.el.ELResolver;
import javax.el.ExpressionFactory;
import javax.el.MethodExpression;
import javax.faces.FacesException;
import javax.faces.application.Application;
import javax.faces.application.NavigationHandler;
import javax.faces.application.ResourceHandler;
import javax.faces.application.StateManager;
import javax.faces.application.ViewHandler;
import javax.faces.application.ProjectStage;
import javax.faces.component.UIComponent;
import javax.faces.component.UIViewRoot;
import javax.faces.component.behavior.Behavior;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;
import javax.faces.convert.DateTimeConverter;
import javax.faces.el.MethodBinding;
import javax.faces.el.PropertyResolver;
import javax.faces.el.ReferenceSyntaxException;
import javax.faces.el.ValueBinding;
import javax.faces.el.VariableResolver;
import javax.faces.event.AbortProcessingException;
import javax.faces.event.ActionListener;
import javax.faces.validator.Validator;

import com.sun.faces.RIConstants;
import com.sun.faces.config.WebConfiguration;
import com.sun.faces.config.WebConfiguration.WebContextInitParameter;
import static com.sun.faces.config.WebConfiguration.BooleanWebContextInitParameter.DateTimeConverterUsesSystemTimezone;
import static com.sun.faces.config.WebConfiguration.BooleanWebContextInitParameter.RegisterConverterPropertyEditors;
import com.sun.faces.el.ELUtils;
import com.sun.faces.el.FacesCompositeELResolver;
import com.sun.faces.el.PropertyResolverImpl;
import com.sun.faces.el.VariableResolverImpl;
import com.sun.faces.spi.InjectionProvider;
import com.sun.faces.util.Cache;
import com.sun.faces.util.Cache.Factory;
import com.sun.faces.util.FacesLogger;
import com.sun.faces.util.MessageUtils;
import com.sun.faces.util.ReflectionUtils;
import com.sun.faces.util.Util;

import java.util.LinkedHashSet;

import javax.faces.event.ExceptionQueuedEvent;
import javax.faces.event.PostAddToViewEvent;
import javax.faces.event.SystemEvent;
import javax.faces.event.SystemEventListener;
import javax.faces.event.SystemEventListenerHolder;
import javax.faces.event.ExceptionQueuedEventContext;

import java.util.List;
import java.util.TimeZone;
import java.util.LinkedHashMap;

import javax.el.ValueExpression;
import javax.faces.application.Resource;
import javax.faces.render.RenderKit;
import javax.faces.render.Renderer;
import javax.faces.view.ViewDeclarationLanguage;


/**
 * 

Application represents a per-web-application * singleton object where applications based on JavaServer Faces (or * implementations wishing to provide extended functionality) can * register application-wide singletons that provide functionality * required by JavaServer Faces. */ public class ApplicationImpl extends Application { // Log instance for this class private static final Logger LOGGER = FacesLogger.APPLICATION.getLogger(); private static final ELContextListener[] EMPTY_EL_CTX_LIST_ARRAY = { }; private static final Map[]> STANDARD_CONV_ID_TO_TYPE_MAP = new HashMap[]>(8, 1.0f); private static final Map,String> STANDARD_TYPE_TO_CONV_ID_MAP = new HashMap,String>(16, 1.0f); static { STANDARD_CONV_ID_TO_TYPE_MAP.put("javax.faces.Byte", new Class[] { Byte.TYPE, Byte.class}); STANDARD_CONV_ID_TO_TYPE_MAP.put("javax.faces.Boolean", new Class[] { Boolean.TYPE, Boolean.class}); STANDARD_CONV_ID_TO_TYPE_MAP.put("javax.faces.Character", new Class[] { Character.TYPE, Character.class}); STANDARD_CONV_ID_TO_TYPE_MAP.put("javax.faces.Short", new Class[] { Short.TYPE, Short.class }); STANDARD_CONV_ID_TO_TYPE_MAP.put("javax.faces.Integer", new Class[] { Integer.TYPE, Integer.class }); STANDARD_CONV_ID_TO_TYPE_MAP.put("javax.faces.Long", new Class[] { Long.TYPE, Long.class }); STANDARD_CONV_ID_TO_TYPE_MAP.put("javax.faces.Float", new Class[] { Float.TYPE, Float.class }); STANDARD_CONV_ID_TO_TYPE_MAP.put("javax.faces.Double", new Class[] { Double.TYPE, Double.class }); for (Map.Entry[]> entry : STANDARD_CONV_ID_TO_TYPE_MAP.entrySet()) { Class[] types = entry.getValue(); String key = entry.getKey(); for (Class clazz : types) { STANDARD_TYPE_TO_CONV_ID_MAP.put(clazz, key); } } } // Relationship Instance Variables private ApplicationAssociate associate = null; private ProjectStage projectStage; private volatile ActionListener actionListener = null; private volatile NavigationHandler navigationHandler = null; private volatile PropertyResolverImpl propertyResolver = null; volatile VariableResolverImpl variableResolver = null; private volatile ViewHandler viewHandler = null; private volatile ResourceHandler resourceHandler; private volatile StateManager stateManager = null; private volatile ArrayList supportedLocales = null; private volatile Locale defaultLocale = null; // // This map stores reference expression | value binding instance // mappings. // // // These four maps store store "identifier" | "class name" // mappings. // private ApplicationInstanceFactoryMetadataMap behaviorMap = null; private ApplicationInstanceFactoryMetadataMap componentMap = null; private ApplicationInstanceFactoryMetadataMap converterIdMap = null; private ApplicationInstanceFactoryMetadataMap validatorMap = null; private Map,Object> converterTypeMap = null; private Set defaultValidatorIds = null; private volatile Map defaultValidatorInfo = null; private volatile String messageBundle = null; private List elContextListeners = null; CompositeELResolver elResolvers = null; FacesCompositeELResolver compositeELResolver = null; private final SystemEventHelper systemEventHelper = new SystemEventHelper(); private final ComponentSystemEventHelper compSysEventHelper = new ComponentSystemEventHelper(); private boolean passDefaultTimeZone; private boolean registerPropertyEditors; private TimeZone systemTimeZone; /** * Constructor */ public ApplicationImpl() { super(); associate = new ApplicationAssociate(this); componentMap = new ApplicationInstanceFactoryMetadataMap(new ConcurrentHashMap()); converterIdMap = new ApplicationInstanceFactoryMetadataMap(new ConcurrentHashMap()); converterTypeMap = new ConcurrentHashMap, Object>(); validatorMap = new ApplicationInstanceFactoryMetadataMap(new ConcurrentHashMap()); defaultValidatorIds = new LinkedHashSet(); behaviorMap = new ApplicationInstanceFactoryMetadataMap(new ConcurrentHashMap()); elContextListeners = new CopyOnWriteArrayList(); propertyResolver = new PropertyResolverImpl(); variableResolver = new VariableResolverImpl(); elResolvers = new CompositeELResolver(); FacesContext ctx = FacesContext.getCurrentInstance(); WebConfiguration webConfig = WebConfiguration.getInstance(ctx.getExternalContext()); passDefaultTimeZone = webConfig.isOptionEnabled(DateTimeConverterUsesSystemTimezone); registerPropertyEditors = webConfig.isOptionEnabled(RegisterConverterPropertyEditors); if (passDefaultTimeZone) { systemTimeZone = TimeZone.getDefault(); } if (LOGGER.isLoggable(Level.FINE)) { LOGGER.log(Level.FINE, "Created Application instance "); } } /** * @see javax.faces.application.Application#publishEvent(FacesContext, Class, Object) */ @Override public void publishEvent(FacesContext context, Class systemEventClass, Object source) { publishEvent(context, systemEventClass, null, source); } /** * @see javax.faces.application.Application#publishEvent(FacesContext, Class, Object) */ @Override public void publishEvent(FacesContext context, Class systemEventClass, Class sourceBaseType, Object source) { Util.notNull("context", context); Util.notNull("systemEventClass", systemEventClass); Util.notNull("source", source); if (!needsProcessing(context, systemEventClass)) { return; } // source is not compatible with the provided base type. // Log a warning that the types are incompatible and return. if (getProjectStage() == ProjectStage.Development && sourceBaseType != null && !sourceBaseType.isInstance(source)) { if (LOGGER.isLoggable(Level.WARNING)) { LOGGER.log(Level.WARNING, "jsf.application.publish.event.base_type_mismatch", new Object[] { source.getClass().getName(), sourceBaseType.getName() }); } return; } try { // The side-effect of calling invokeListenersFor // will create a SystemEvent object appropriate to event/source // combination. This event will be passed on subsequent invocations // of invokeListenersFor SystemEvent event; // Look for and invoke any listeners stored on the source instance. event = invokeComponentListenersFor(systemEventClass, source); // Look for and invoke any 'view' listeners event = invokeViewListenersFor(context, systemEventClass, event, source); // look for and invoke any listeners stored on the application // using source type. event = invokeListenersFor(systemEventClass, event, source, sourceBaseType, true); // look for and invoke any listeners not specific to the source class invokeListenersFor(systemEventClass, event, source, null, false); } catch (AbortProcessingException ape) { context.getApplication().publishEvent(context, ExceptionQueuedEvent.class, new ExceptionQueuedEventContext(context, ape)); } } /** * @see Application#subscribeToEvent(Class, Class, javax.faces.event.SystemEventListener) */ @Override public void subscribeToEvent(Class systemEventClass, Class sourceClass, SystemEventListener listener) { Util.notNull("systemEventClass", systemEventClass); Util.notNull("listener", listener); Set listeners = getListeners(systemEventClass, sourceClass); listeners.add(listener); } /** * @see Application#subscribeToEvent(Class, javax.faces.event.SystemEventListener) */ @Override public void subscribeToEvent(Class systemEventClass, SystemEventListener listener) { subscribeToEvent(systemEventClass, null, listener); } /** * @see Application#unsubscribeFromEvent(Class, Class, javax.faces.event.SystemEventListener) */ @Override public void unsubscribeFromEvent(Class systemEventClass, Class sourceClass, SystemEventListener listener) { Util.notNull("systemEventClass", systemEventClass); Util.notNull("listener", listener); Set listeners = getListeners(systemEventClass, sourceClass); if (listeners != null) { listeners.remove(listener); } } /** * @see Application#unsubscribeFromEvent(Class, javax.faces.event.SystemEventListener) */ @Override public void unsubscribeFromEvent(Class systemEventClass, SystemEventListener listener) { unsubscribeFromEvent(systemEventClass, null, listener); } /** * @see javax.faces.application.Application#addELContextListener(javax.el.ELContextListener) */ @Override public void addELContextListener(ELContextListener listener) { if (listener != null) { elContextListeners.add(listener); } } /** * @see javax.faces.application.Application#removeELContextListener(javax.el.ELContextListener) */ @Override public void removeELContextListener(ELContextListener listener) { if (listener != null) { elContextListeners.remove(listener); } } /** * @see javax.faces.application.Application#getELContextListeners() */ @Override public ELContextListener [] getELContextListeners() { if (!elContextListeners.isEmpty()) { return (elContextListeners.toArray( new ELContextListener[elContextListeners.size()])); } else { return (EMPTY_EL_CTX_LIST_ARRAY); } } /** * @see javax.faces.application.Application#getExpressionFactory() */ @Override public ExpressionFactory getExpressionFactory() { return associate.getExpressionFactory(); } /** * @see javax.faces.application.Application#evaluateExpressionGet(javax.faces.context.FacesContext, String, Class) */ @Override public T evaluateExpressionGet(FacesContext context, String expression, Class expectedType) throws ELException { ValueExpression ve = getExpressionFactory().createValueExpression(context.getELContext(), expression, expectedType); //noinspection unchecked return (T)(ve.getValue(context.getELContext())); } /** * @see javax.faces.application.Application#createComponent(javax.el.ValueExpression, javax.faces.context.FacesContext, String) */ @Override public UIComponent createComponent(ValueExpression componentExpression, FacesContext context, String componentType) throws FacesException { Util.notNull("componentExpression", componentExpression); Util.notNull("context", context); Util.notNull("componentType", componentType); return createComponentApplyAnnotations(context, componentExpression, componentType, null, true); } /** * @see javax.faces.application.Application#getELResolver() */ @Override public ELResolver getELResolver() { if (compositeELResolver == null) { performOneTimeELInitialization(); } return compositeELResolver; } /** * @see javax.faces.application.Application#addELResolver(javax.el.ELResolver) */ @Override public void addELResolver(ELResolver resolver) { if (associate.hasRequestBeenServiced()) { throw new IllegalStateException( MessageUtils.getExceptionMessageString( MessageUtils.ILLEGAL_ATTEMPT_SETTING_APPLICATION_ARTIFACT_ID, "ELResolver")); } elResolvers.add(resolver); } /** * @see javax.faces.application.Application#getProjectStage() */ @Override public ProjectStage getProjectStage() { if (projectStage == null) { WebConfiguration webConfig = WebConfiguration.getInstance( FacesContext.getCurrentInstance().getExternalContext()); String value = webConfig.getEnvironmentEntry(WebConfiguration.WebEnvironmentEntry.ProjectStage); if (value != null) { if (LOGGER.isLoggable(Level.FINE)) { LOGGER.log(Level.FINE, "ProjectStage configured via JNDI: {0}", value); } } else { value = webConfig.getOptionValue(WebContextInitParameter.JavaxFacesProjectStage); if (value != null) { if (LOGGER.isLoggable(Level.FINE)) { LOGGER.log(Level.FINE, "ProjectStage configured via servlet context init parameter: {0}", value); } } } if (value != null) { try { projectStage = ProjectStage.valueOf(value); } catch (IllegalArgumentException iae) { if (LOGGER.isLoggable(Level.INFO)) { LOGGER.log(Level.INFO, "Unable to discern ProjectStage for value {0}.", value); } } } if (projectStage == null) { projectStage = ProjectStage.Production; } if (projectStage == ProjectStage.Development) { subscribeToEvent(PostAddToViewEvent.class, new ValidateComponentNesting()); } } return projectStage; } public CompositeELResolver getApplicationELResolvers() { return elResolvers; } /** * @see javax.faces.application.Application#getActionListener() */ public ActionListener getActionListener() { return actionListener; } /** * @see javax.faces.application.Application#getViewHandler() */ public ViewHandler getViewHandler() { return viewHandler; } /** * @see javax.faces.application.Application#setViewHandler(javax.faces.application.ViewHandler) */ public synchronized void setViewHandler(ViewHandler viewHandler) { Util.notNull("viewHandler", viewHandler); if (associate.hasRequestBeenServiced()) { throw new IllegalStateException( MessageUtils.getExceptionMessageString( MessageUtils.ILLEGAL_ATTEMPT_SETTING_APPLICATION_ARTIFACT_ID, "ViewHandler")); } this.viewHandler = viewHandler; if (LOGGER.isLoggable(Level.FINE)) { LOGGER.log(Level.FINE, MessageFormat.format("set ViewHandler Instance to ''{0}''", viewHandler.getClass().getName())); } } /** * @see javax.faces.application.Application#getResourceHandler() */ @Override public ResourceHandler getResourceHandler() { return resourceHandler; } /** * @see javax.faces.application.Application#setResourceHandler(javax.faces.application.ResourceHandler) */ @Override public synchronized void setResourceHandler(ResourceHandler resourceHandler) { Util.notNull("resourceHandler", resourceHandler); if (associate.hasRequestBeenServiced()) { throw new IllegalStateException( MessageUtils.getExceptionMessageString( MessageUtils.ILLEGAL_ATTEMPT_SETTING_APPLICATION_ARTIFACT_ID, "ResourceHandler")); } this.resourceHandler = resourceHandler; if (LOGGER.isLoggable(Level.FINE)) { LOGGER.log(Level.FINE, "set ResourceHandler Instance to ''{0}''", resourceHandler.getClass().getName()); } } /** * @see javax.faces.application.Application#getStateManager() */ public StateManager getStateManager() { return stateManager; } /** * @see javax.faces.application.Application#setStateManager(javax.faces.application.StateManager) */ public synchronized void setStateManager(StateManager stateManager) { Util.notNull("stateManager", stateManager); if (associate.hasRequestBeenServiced()) { throw new IllegalStateException( MessageUtils.getExceptionMessageString( MessageUtils.ILLEGAL_ATTEMPT_SETTING_APPLICATION_ARTIFACT_ID, "StateManager")); } this.stateManager = stateManager; if (LOGGER.isLoggable(Level.FINE)) { LOGGER.log(Level.FINE, MessageFormat.format("set StateManager Instance to ''{0}''", stateManager.getClass().getName())); } } /** * @see Application#setActionListener(javax.faces.event.ActionListener) */ public synchronized void setActionListener(ActionListener actionListener) { Util.notNull("actionListener", actionListener); this.actionListener = actionListener; if (LOGGER.isLoggable(Level.FINE)) { LOGGER.fine(MessageFormat.format("set ActionListener Instance to ''{0}''", actionListener.getClass().getName())); } } /** * @see javax.faces.application.Application#getNavigationHandler() */ public NavigationHandler getNavigationHandler() { return navigationHandler; } /** * @see javax.faces.application.Application#setNavigationHandler(javax.faces.application.NavigationHandler) */ public synchronized void setNavigationHandler(NavigationHandler navigationHandler) { Util.notNull("navigationHandler", navigationHandler); this.navigationHandler = navigationHandler; if (LOGGER.isLoggable(Level.FINE)) { LOGGER.fine(MessageFormat.format("set NavigationHandler Instance to ''{0}''", navigationHandler.getClass().getName())); } } /** * @see javax.faces.application.Application#setPropertyResolver(javax.faces.el.PropertyResolver) */ @SuppressWarnings("deprecation") public PropertyResolver getPropertyResolver() { if (compositeELResolver == null) { performOneTimeELInitialization(); } return propertyResolver; } /** * @see javax.faces.application.Application#getResourceBundle(javax.faces.context.FacesContext, String) */ @Override public ResourceBundle getResourceBundle(FacesContext context, String var) { Util.notNull("context", context); Util.notNull("var", var); return associate.getResourceBundle(context, var); } /** * @see javax.faces.application.Application#setPropertyResolver(javax.faces.el.PropertyResolver) */ @SuppressWarnings("deprecation") public void setPropertyResolver(PropertyResolver resolver) { // Throw Illegal State Exception if a PropertyResolver is set after // a request has been processed. if (associate.hasRequestBeenServiced()) { throw new IllegalStateException( MessageUtils.getExceptionMessageString( MessageUtils.ILLEGAL_ATTEMPT_SETTING_APPLICATION_ARTIFACT_ID, "PropertyResolver")); } if (resolver == null) { String message = MessageUtils.getExceptionMessageString (MessageUtils.NULL_PARAMETERS_ERROR_MESSAGE_ID, "resolver"); throw new NullPointerException(message); } propertyResolver.setDelegate(ELUtils.getDelegatePR(associate, true)); associate.setLegacyPropertyResolver(resolver); propertyResolver = new PropertyResolverImpl(); if (LOGGER.isLoggable(Level.FINE)) { LOGGER.fine(MessageFormat.format("set PropertyResolver Instance to ''{0}''", resolver.getClass().getName())); } } /** * @see javax.faces.application.Application#createMethodBinding(String, Class[]) */ @SuppressWarnings("deprecation") public MethodBinding createMethodBinding(String ref, Class params[]) { Util.notNull("ref", ref); if (!(ref.startsWith("#{") && ref.endsWith("}"))) { if (LOGGER.isLoggable(Level.FINE)) { LOGGER.fine(MessageFormat.format("Expression ''{0}'' does not follow the syntax #{...}", ref)); } throw new ReferenceSyntaxException(ref); } FacesContext context = FacesContext.getCurrentInstance(); MethodExpression result; try { // return a MethodBinding that wraps a MethodExpression. if (null == params) { params = RIConstants.EMPTY_CLASS_ARGS; } result = getExpressionFactory(). createMethodExpression(context.getELContext(), ref, null, params); } catch (ELException elex) { throw new ReferenceSyntaxException(elex); } return (new MethodBindingMethodExpressionAdapter(result)); } /** * @see javax.faces.application.Application#createValueBinding(String) */ @SuppressWarnings("deprecation") public ValueBinding createValueBinding(String ref) throws ReferenceSyntaxException { Util.notNull("ref", ref); ValueExpression result; FacesContext context = FacesContext.getCurrentInstance(); // return a ValueBinding that wraps a ValueExpression. try { result= getExpressionFactory(). createValueExpression(context.getELContext(),ref, Object.class); } catch (ELException elex) { throw new ReferenceSyntaxException(elex); } return (new ValueBindingValueExpressionAdapter(result)); } /** * @see javax.faces.application.Application#getVariableResolver() */ @SuppressWarnings("deprecation") public VariableResolver getVariableResolver() { if (compositeELResolver == null) { performOneTimeELInitialization(); } return variableResolver; } /** * @see javax.faces.application.Application#setVariableResolver(javax.faces.el.VariableResolver) */ @SuppressWarnings("deprecation") public void setVariableResolver(VariableResolver resolver) { Util.notNull("variableResolver", resolver); if (associate.hasRequestBeenServiced()) { throw new IllegalStateException( MessageUtils.getExceptionMessageString( MessageUtils.ILLEGAL_ATTEMPT_SETTING_APPLICATION_ARTIFACT_ID, "VariableResolver")); } variableResolver.setDelegate(ELUtils.getDelegateVR(associate, true)); associate.setLegacyVariableResolver(resolver); if (LOGGER.isLoggable(Level.FINE)) { LOGGER.fine(MessageFormat.format("set VariableResolver Instance to ''{0}''", variableResolver.getClass().getName())); } } /** * @see javax.faces.application.Application#addBehavior(String, String) */ public void addBehavior(String behaviorId, String behaviorClass) { Util.notNull("behaviorId", behaviorId); Util.notNull("behaviorClass", behaviorClass); if (LOGGER.isLoggable(Level.FINE) && behaviorMap.containsKey(behaviorId)) { LOGGER.log(Level.FINE, "behaviorId {0} has already been registered. Replacing existing behavior class type {1} with {2}.", new Object[] { behaviorId, behaviorMap.get(behaviorId), behaviorClass }); } behaviorMap.put(behaviorId, behaviorClass); if (LOGGER.isLoggable(Level.FINE)) { LOGGER.fine(MessageFormat.format("added behavior of type ''{0}'' class ''{1}''", behaviorId, behaviorClass)); } } /** * @see javax.faces.application.Application#createBehavior(String) */ public Behavior createBehavior(String behaviorId) throws FacesException { Util.notNull("behaviorId", behaviorId); Behavior returnVal = (Behavior) newThing(behaviorId, behaviorMap); if (returnVal == null) { Object[] params = {behaviorId}; if (LOGGER.isLoggable(Level.SEVERE)) { LOGGER.log(Level.SEVERE, "jsf.cannot_instantiate_behavior_error", params); } throw new FacesException(MessageUtils.getExceptionMessageString( MessageUtils.NAMED_OBJECT_NOT_FOUND_ERROR_MESSAGE_ID, params)); } if (LOGGER.isLoggable(Level.FINE)) { LOGGER.fine(MessageFormat.format("created behavior of type ''{0}''", behaviorId)); } associate.getAnnotationManager().applyBehaviorAnnotations(FacesContext.getCurrentInstance(), returnVal); return returnVal; } /** * @see javax.faces.application.Application#getBehaviorIds() */ public Iterator getBehaviorIds() { return behaviorMap.keySet().iterator(); } /** * @see javax.faces.application.Application#addComponent(String, String) */ public void addComponent(String componentType, String componentClass) { Util.notNull("componentType", componentType); Util.notNull("componentType", componentClass); if (LOGGER.isLoggable(Level.FINE) && componentMap.containsKey(componentType)) { LOGGER.log(Level.FINE, "componentType {0} has already been registered. Replacing existing component class type {1} with {2}.", new Object[] { componentType, componentMap.get(componentType), componentClass }); } componentMap.put(componentType, componentClass); if (LOGGER.isLoggable(Level.FINE)) { LOGGER.fine(MessageFormat.format("added component of type ''{0}'' and class ''{1}''", componentType, componentClass)); } } /** * @see javax.faces.application.Application#createComponent(String) */ public UIComponent createComponent(String componentType) throws FacesException { Util.notNull("componentType", componentType); return createComponentApplyAnnotations(FacesContext.getCurrentInstance(), componentType, null, true); } /** * @see javax.faces.application.Application#createComponent(javax.faces.context.FacesContext, javax.faces.application.Resource) */ @Override public UIComponent createComponent(FacesContext context, Resource componentResource) throws FacesException { // RELEASE_PENDING (rlubke,driscoll) this method needs review. Util.notNull("context", context); Util.notNull("componentResource", componentResource); UIComponent result = null; // use the application defined in the FacesContext as we may be calling // overriden methods Application app = context.getApplication(); ViewDeclarationLanguage pdl = app.getViewHandler().getViewDeclarationLanguage(context, context.getViewRoot().getViewId()); BeanInfo componentMetadata = pdl.getComponentMetadata(context, componentResource); if (null != componentMetadata){ BeanDescriptor componentBeanDescriptor = componentMetadata.getBeanDescriptor(); // Step 1. See if the composite component author explicitly // gave a componentType as part of the composite component metadata ValueExpression ve = (ValueExpression) componentBeanDescriptor.getValue(UIComponent.COMPOSITE_COMPONENT_TYPE_KEY); if (null != ve) { String componentType = (String) ve.getValue(context.getELContext()); if (null != componentType && 0 < componentType.length()) { result = app.createComponent(componentType); } } } // Step 2. If that didn't work, if a script based resource can be // found for the scriptComponentResource, // see if a component can be generated from it if (null == result) { Resource scriptComponentResource = pdl.getScriptComponentResource(context, componentResource); if (null != scriptComponentResource) { result = createComponentFromScriptResource(context, scriptComponentResource, componentResource); } } // Step 3. Use the libraryName of the resource as the java package // and use the resourceName as the class name. See // if a Java class can be loaded if (null == result) { String packageName = componentResource.getLibraryName(); String className = componentResource.getResourceName(); className = packageName + '.' + className.substring(0, className.lastIndexOf('.')); try { Class clazz = (Class) componentMap.get(className); if (clazz == null) { clazz = Util.loadClass(className, this); } if (clazz != ComponentResourceClassNotFound.class) { if (!associate.isDevModeEnabled()) { componentMap.put(className, clazz); } result = (UIComponent) clazz.newInstance(); } } catch (ClassNotFoundException ex) { if (!associate.isDevModeEnabled()) { componentMap.put(className, ComponentResourceClassNotFound.class); } } catch (InstantiationException ie) { throw new FacesException(ie); } catch (IllegalAccessException iae) { throw new FacesException(iae); } catch (ClassCastException cce) { throw new FacesException(cce); } catch (Exception otherwise) { if (LOGGER.isLoggable(Level.SEVERE)) { LOGGER.log(Level.SEVERE, otherwise.toString(), otherwise); } } } // Step 4. Use javax.faces.NamingContainer as the component type if (null == result) { result = app.createComponent("javax.faces.NamingContainer"); } assert (null != result); result.setRendererType("javax.faces.Composite"); Map attrs = result.getAttributes(); attrs.put(Resource.COMPONENT_RESOURCE_KEY, componentResource); attrs.put(UIComponent.BEANINFO_KEY, componentMetadata); associate.getAnnotationManager().applyComponentAnnotations(context, result); pushDeclaredDefaultValuesToAttributesMap(context, componentMetadata, attrs, result); return result; } /* * This method makes it so that any cc:attribute elements that have * a "default" attribute value have those values pushed into the * composite component attribute map so that programmatic access * (as opposed to EL access) will find the attribute values. * */ private void pushDeclaredDefaultValuesToAttributesMap(FacesContext context, BeanInfo componentMetadata, Map attrs, UIComponent component) { PropertyDescriptor[] declaredAttributes = componentMetadata.getPropertyDescriptors(); Object defaultValue; String key; Collection attributesWithDeclaredDefaultValues = null; PropertyDescriptor[] pd = null; for (PropertyDescriptor cur : declaredAttributes) { defaultValue = cur.getValue("default"); if (null != defaultValue) { key = cur.getName(); boolean isLiteralText = false; if (defaultValue instanceof ValueExpression) { isLiteralText = ((ValueExpression)defaultValue).isLiteralText(); if (isLiteralText) { defaultValue = ((ValueExpression)defaultValue).getValue(context.getELContext()); } } // ensure this attribute is not a method-signature. method-signature // declared default values are handled in retargetMethodExpressions. if (null == cur.getValue("method-signature") || null != cur.getValue("type")) { if (null == attributesWithDeclaredDefaultValues) { BeanDescriptor desc = componentMetadata.getBeanDescriptor(); attributesWithDeclaredDefaultValues = (Collection) desc.getValue(UIComponent.ATTRS_WITH_DECLARED_DEFAULT_VALUES); if (null == attributesWithDeclaredDefaultValues) { attributesWithDeclaredDefaultValues = new ArrayList(); desc.setValue(UIComponent.ATTRS_WITH_DECLARED_DEFAULT_VALUES, attributesWithDeclaredDefaultValues); } } attributesWithDeclaredDefaultValues.add(key); // Only store the attribute if it is literal text. If it // is a ValueExpression, it will be handled explicitly in // CompositeComponentAttributesELResolver.ExpressionEvalMap.get(). // If it is a MethodExpression, it will be dealt with in // retargetMethodExpressions. if (isLiteralText) { try { if (null == pd) { pd = Introspector.getBeanInfo(component.getClass()).getPropertyDescriptors(); } } catch (IntrospectionException e) { throw new FacesException(e); } defaultValue = convertValueToTypeIfNecessary(key, defaultValue, pd); attrs.put(key, defaultValue); } } } } } /** * @see javax.faces.application.Application#createComponent(javax.faces.el.ValueBinding, javax.faces.context.FacesContext, String) */ @SuppressWarnings("deprecation") public UIComponent createComponent(ValueBinding componentBinding, FacesContext context, String componentType) throws FacesException { Util.notNull("componentBinding", componentBinding); Util.notNull("context", context); Util.notNull("componentType", componentType); Object result; boolean createOne = false; try { result = componentBinding.getValue(context); if (result != null) { createOne = (!(result instanceof UIComponent)); } if (result == null || createOne) { result = this.createComponentApplyAnnotations(context, componentType, null, false); componentBinding.setValue(context, result); } } catch (Exception ex) { throw new FacesException(ex); } return (UIComponent) result; } /** * @see javax.faces.application.Application#createComponent(javax.el.ValueExpression, javax.faces.context.FacesContext, String, String) */ @Override public UIComponent createComponent(ValueExpression componentExpression, FacesContext context, String componentType, String rendererType) { Util.notNull("componentExpression", componentExpression); Util.notNull("context", context); Util.notNull("componentType", componentType); return createComponentApplyAnnotations(context, componentExpression, componentType, rendererType, true); } /** * @see javax.faces.application.Application#createComponent(javax.faces.context.FacesContext, String, String) */ @Override public UIComponent createComponent(FacesContext context, String componentType, String rendererType) { Util.notNull("context", context); Util.notNull("componentType", componentType); return createComponentApplyAnnotations(context, componentType, rendererType, true); } /** * @see javax.faces.application.Application#getComponentTypes() */ public Iterator getComponentTypes() { return componentMap.keySet().iterator(); } /** * @see javax.faces.application.Application#addConverter(String, String) */ public void addConverter(String converterId, String converterClass) { Util.notNull("converterId", converterId); Util.notNull("converterClass", converterClass); if (LOGGER.isLoggable(Level.FINE) && converterIdMap.containsKey(converterId)) { LOGGER.log(Level.FINE, "converterId {0} has already been registered. Replacing existing converter class type {1} with {2}.", new Object[] { converterId, converterIdMap.get(converterId), converterClass }); } converterIdMap.put(converterId, converterClass); Class[] types = STANDARD_CONV_ID_TO_TYPE_MAP.get(converterId); if (types != null) { for (Class clazz : types) { // go directly against map to prevent cyclic method calls converterTypeMap.put(clazz, converterClass); addPropertyEditorIfNecessary(clazz); } } if (LOGGER.isLoggable(Level.FINE)) { LOGGER.fine(MessageFormat.format("added converter of type ''{0}'' and class ''{1}''", converterId, converterClass)); } } /** * @see javax.faces.application.Application#addConverter(Class, String) */ public void addConverter(Class targetClass, String converterClass) { Util.notNull("targetClass", targetClass); Util.notNull("converterClass", converterClass); String converterId = STANDARD_TYPE_TO_CONV_ID_MAP.get(targetClass); if (converterId != null) { addConverter(converterId, converterClass); } else { if (LOGGER.isLoggable(Level.FINE) && converterTypeMap .containsKey(targetClass)) { LOGGER.log(Level.FINE, "converter target class {0} has already been registered. Replacing existing converter class type {1} with {2}.", new Object[]{ targetClass.getName(), converterTypeMap.get(targetClass), converterClass}); } converterTypeMap.put(targetClass, converterClass); addPropertyEditorIfNecessary(targetClass); } if (LOGGER.isLoggable(Level.FINE)) { LOGGER.fine(MessageFormat.format("added converter of class type ''{0}''", converterClass)); } } private final String [] STANDARD_BY_TYPE_CONVERTER_CLASSES = { "java.math.BigDecimal", "java.lang.Boolean", "java.lang.Byte", "java.lang.Character", "java.lang.Double", "java.lang.Float", "java.lang.Integer", "java.lang.Long", "java.lang.Short", "java.lang.Enum" }; /** * Helper method to convert a value to a type as defined in PropertyDescriptor(s) * @param name * @param value * @param pd * @return value */ private Object convertValueToTypeIfNecessary(String name, Object value, PropertyDescriptor[] pd) { for (PropertyDescriptor aPd : pd) { if (aPd.getName().equals(name)) { value = getExpressionFactory().coerceToType(value, aPd.getPropertyType()); break; } } return value; } /** *

To enable EL Coercion to use JSF Custom converters, this * method will call PropertyEditorManager.registerEditor(), * passing the ConverterPropertyEditor class for the * targetClass if the target class is not one of the standard * by-type converter target classes. * @param targetClass the target class for which a PropertyEditory may or * may not be created */ private void addPropertyEditorIfNecessary(Class targetClass) { if (!registerPropertyEditors) { return; } PropertyEditor editor = PropertyEditorManager.findEditor(targetClass); if (null != editor) { return; } String className = targetClass.getName(); // Don't add a PropertyEditor for the standard by-type converters. if (targetClass.isPrimitive()) { return; } for (String standardClass : STANDARD_BY_TYPE_CONVERTER_CLASSES) { if (-1 != standardClass.indexOf(className)) { return; } } Class editorClass = ConverterPropertyEditorFactory.getDefaultInstance().definePropertyEditorClassFor(targetClass); if (editorClass != null) { PropertyEditorManager.registerEditor(targetClass, editorClass); } else { if (LOGGER.isLoggable(Level.WARNING)) { LOGGER.warning(MessageFormat.format("definePropertyEditorClassFor({0}) returned null.", targetClass.getName())); } } } private void performOneTimeELInitialization() { if (null != compositeELResolver) { throw new IllegalStateException("Class invariant invalidated: " + "The Application instance's ELResolver is not null " + "and it should be."); } associate.initializeELResolverChains(); } /** * @see javax.faces.application.Application#createConverter(String) */ public Converter createConverter(String converterId) { Util.notNull("converterId", converterId); Converter returnVal = (Converter) newThing(converterId, converterIdMap); if (returnVal == null) { Object[] params = {converterId}; if (LOGGER.isLoggable(Level.SEVERE)) { LOGGER.log(Level.SEVERE, "jsf.cannot_instantiate_converter_error", converterId); } throw new FacesException(MessageUtils.getExceptionMessageString( MessageUtils.NAMED_OBJECT_NOT_FOUND_ERROR_MESSAGE_ID, params)); } if (LOGGER.isLoggable(Level.FINE)) { LOGGER.fine(MessageFormat.format("created converter of type ''{0}''", converterId)); } if (passDefaultTimeZone && returnVal instanceof DateTimeConverter) { ((DateTimeConverter) returnVal).setTimeZone(systemTimeZone); } associate.getAnnotationManager().applyConverterAnnotations(FacesContext.getCurrentInstance(), returnVal); return returnVal; } /** * @see javax.faces.application.Application#createConverter(Class) */ public Converter createConverter(Class targetClass) { Util.notNull("targetClass", targetClass); Converter returnVal = (Converter) newConverter(targetClass, converterTypeMap,targetClass); if (returnVal != null) { if (LOGGER.isLoggable(Level.FINE)) { LOGGER.fine(MessageFormat.format("Created converter of type ''{0}''", returnVal.getClass().getName())); } if (passDefaultTimeZone && returnVal instanceof DateTimeConverter) { ((DateTimeConverter) returnVal).setTimeZone(systemTimeZone); } associate.getAnnotationManager().applyConverterAnnotations(FacesContext.getCurrentInstance(), returnVal); return returnVal; } //Search for converters registered to interfaces implemented by //targetClass Class[] interfaces = targetClass.getInterfaces(); if (interfaces != null) { for (int i = 0; i < interfaces.length; i++) { returnVal = createConverterBasedOnClass(interfaces[i], targetClass); if (returnVal != null) { if (LOGGER.isLoggable(Level.FINE)) { LOGGER.fine(MessageFormat.format("Created converter of type ''{0}''", returnVal.getClass().getName())); } if (passDefaultTimeZone && returnVal instanceof DateTimeConverter) { ((DateTimeConverter) returnVal) .setTimeZone(systemTimeZone); } associate.getAnnotationManager().applyConverterAnnotations(FacesContext.getCurrentInstance(), returnVal); return returnVal; } } } //Search for converters registered to superclasses of targetClass Class superclass = targetClass.getSuperclass(); if (superclass != null) { returnVal = createConverterBasedOnClass(superclass, targetClass); if (returnVal != null) { if (LOGGER.isLoggable(Level.FINE)) { LOGGER.fine(MessageFormat.format("Created converter of type ''{0}''", returnVal.getClass().getName())); } if (passDefaultTimeZone && returnVal instanceof DateTimeConverter) { ((DateTimeConverter) returnVal).setTimeZone(systemTimeZone); } associate.getAnnotationManager().applyConverterAnnotations(FacesContext.getCurrentInstance(), returnVal); return returnVal; } } return returnVal; } protected Converter createConverterBasedOnClass(Class targetClass, Class baseClass) { Converter returnVal = (Converter) newConverter(targetClass, converterTypeMap, baseClass); if (returnVal != null) { if (LOGGER.isLoggable(Level.FINE)) { LOGGER.fine(MessageFormat.format("Created converter of type ''{0}''", returnVal.getClass().getName())); } return returnVal; } //Search for converters registered to interfaces implemented by //targetClass Class[] interfaces = targetClass.getInterfaces(); if (interfaces != null) { for (int i = 0; i < interfaces.length; i++) { returnVal = createConverterBasedOnClass(interfaces[i], null); if (returnVal != null) { if (LOGGER.isLoggable(Level.FINE)) { LOGGER.fine(MessageFormat.format("Created converter of type ''{0}''", returnVal.getClass().getName())); } return returnVal; } } } //Search for converters registered to superclasses of targetClass Class superclass = targetClass.getSuperclass(); if (superclass != null) { returnVal = createConverterBasedOnClass(superclass, null); if (returnVal != null) { if (LOGGER.isLoggable(Level.FINE)) { LOGGER.fine(MessageFormat.format("Created converter of type ''{0}''", returnVal.getClass().getName())); } return returnVal; } } return returnVal; } /** * @see javax.faces.application.Application#getConverterIds() */ public Iterator getConverterIds() { return converterIdMap.keySet().iterator(); } /** * @see javax.faces.application.Application#getConverterTypes() */ public Iterator> getConverterTypes() { return converterTypeMap.keySet().iterator(); } /** * @see javax.faces.application.Application#getSupportedLocales() */ public Iterator getSupportedLocales() { if (null != supportedLocales) { return supportedLocales.iterator(); } else { return Collections.emptyList().iterator(); } } /** * @see javax.faces.application.Application#setSupportedLocales(java.util.Collection) */ public synchronized void setSupportedLocales(Collection newLocales) { Util.notNull("newLocales", newLocales); supportedLocales = new ArrayList(newLocales); if (LOGGER.isLoggable(Level.FINE)) { LOGGER.log(Level.FINE, MessageFormat.format("set Supported Locales ''{0}''", supportedLocales.toString())); } } /** * @see javax.faces.application.Application#getDefaultLocale() */ public Locale getDefaultLocale() { return defaultLocale; } /** * @see javax.faces.application.Application#setDefaultLocale(java.util.Locale) */ public synchronized void setDefaultLocale(Locale locale) { Util.notNull("locale", locale); defaultLocale = locale; if (LOGGER.isLoggable(Level.FINE)) { LOGGER.log(Level.FINE, (MessageFormat.format("set defaultLocale ''{0}''", defaultLocale.getClass().getName()))); } } protected String defaultRenderKitId = null; /** * @see javax.faces.application.Application#getDefaultRenderKitId() */ public String getDefaultRenderKitId() { return defaultRenderKitId; } /** * @see javax.faces.application.Application#setDefaultRenderKitId(String) */ public void setDefaultRenderKitId(String renderKitId) { defaultRenderKitId = renderKitId; } /** * @see javax.faces.application.Application#addValidator(String, String) */ public void addValidator(String validatorId, String validatorClass) { Util.notNull("validatorId", validatorId); Util.notNull("validatorClass", validatorClass); if (LOGGER.isLoggable(Level.FINE) && validatorMap.containsKey(validatorId)) { LOGGER.log(Level.FINE, "validatorId {0} has already been registered. Replacing existing validator class type {1} with {2}.", new Object[] { validatorId, validatorMap.get(validatorId), validatorClass }); } validatorMap.put(validatorId, validatorClass); if (LOGGER.isLoggable(Level.FINE)) { LOGGER.fine(MessageFormat.format("added validator of type ''{0}'' class ''{1}''", validatorId, validatorClass)); } } /** * @see javax.faces.application.Application#createValidator(String) */ public Validator createValidator(String validatorId) throws FacesException { Util.notNull("validatorId", validatorId); Validator returnVal = (Validator) newThing(validatorId, validatorMap); if (returnVal == null) { Object[] params = {validatorId}; if (LOGGER.isLoggable(Level.SEVERE)) { LOGGER.log(Level.SEVERE, "jsf.cannot_instantiate_validator_error", params); } throw new FacesException(MessageUtils.getExceptionMessageString( MessageUtils.NAMED_OBJECT_NOT_FOUND_ERROR_MESSAGE_ID, params)); } if (LOGGER.isLoggable(Level.FINE)) { LOGGER.fine(MessageFormat.format("created validator of type ''{0}''", validatorId)); } associate.getAnnotationManager().applyValidatorAnnotations(FacesContext.getCurrentInstance(), returnVal); return returnVal; } /** * @see javax.faces.application.Application#getValidatorIds() */ public Iterator getValidatorIds() { return validatorMap.keySet().iterator(); } /** * @see javax.faces.application.Application#addDefaultValidatorId(String) */ public synchronized void addDefaultValidatorId(String validatorId) { Util.notNull("validatorId", validatorId); defaultValidatorInfo = null; defaultValidatorIds.add(validatorId); } /** * @see javax.faces.application.Application#getDefaultValidatorInfo() */ public Map getDefaultValidatorInfo() { if (defaultValidatorInfo == null) { synchronized (this) { if (defaultValidatorInfo == null) { defaultValidatorInfo = new LinkedHashMap(); if (!defaultValidatorIds.isEmpty()) { for (String id : defaultValidatorIds) { String validatorClass; Object result = validatorMap.get(id); if (null != result) { if (result instanceof Class) { validatorClass = ((Class) result).getName(); } else { validatorClass = result.toString(); } defaultValidatorInfo.put(id, validatorClass); } } } } } defaultValidatorInfo = Collections.unmodifiableMap(defaultValidatorInfo); } return defaultValidatorInfo; } /** * @see javax.faces.application.Application#setMessageBundle(String) */ public synchronized void setMessageBundle(String messageBundle) { Util.notNull("messageBundle", messageBundle); this.messageBundle = messageBundle; if (LOGGER.isLoggable(Level.FINE)) { LOGGER.log(Level.FINE, MessageFormat.format("set messageBundle ''{0}''", messageBundle)); } } /** * @see javax.faces.application.Application#getMessageBundle() */ public String getMessageBundle() { return messageBundle; } /** *

PRECONDITIONS: the values in the Map are either Strings * representing fully qualified java class names, or java.lang.Class * instances.

*

ALGORITHM: Look in the argument map for a value for the argument * key. If found, if the value is instanceof String, assume the String * specifies a fully qualified java class name and obtain the * java.lang.Class instance for that String using Util.loadClass(). * Replace the String instance in the argument map with the Class * instance. If the value is instanceof Class, proceed. Assert that the * value is either instanceof java.lang.Class or java.lang.String.

*

Now that you have a java.lang.class, call its newInstance and * return it as the result of this method.

* * @param key Used to look up the value in the Map. * @param map The Map that will be searched. * @return The new object instance. */ protected Object newThing(String key, ApplicationInstanceFactoryMetadataMap map) { assert (key != null && map != null); Object result; Class clazz; Object value; value = map.get(key); if (value == null) { return null; } assert (value instanceof String || value instanceof Class); if (value instanceof String) { String cValue = (String) value; try { clazz = Util.loadClass(cValue, value); if (!associate.isDevModeEnabled()) { map.put(key, clazz); } else { map.scanForAnnotations(key, clazz); } assert (clazz != null); } catch (Exception e) { throw new FacesException(e.getMessage(), e); } } else { clazz = (Class) value; } try { result = clazz.newInstance(); } catch (Throwable t) { Throwable previousT; do { previousT = t; if (LOGGER.isLoggable(Level.SEVERE)) { LOGGER.log(Level.SEVERE, "Unable to load class: ", t); } } while (null != (t = t.getCause())); t = previousT; throw new FacesException((MessageUtils.getExceptionMessageString( MessageUtils.CANT_INSTANTIATE_CLASS_ERROR_MESSAGE_ID, clazz.getName())), t); } if (map.hasAnnotations(key)) { InjectionProvider injectionProvider = associate.getInjectionProvider(); try { injectionProvider.invokePostConstruct(result); } catch (InjectionProviderException ex) { LOGGER.log(Level.SEVERE, "Unable to invoke @PostConstruct annotated method on instance " + key, ex); throw new FacesException(ex); } try { injectionProvider.inject(result); } catch (InjectionProviderException ex) { LOGGER.log(Level.SEVERE, "Unable to inject instance" + key, ex); throw new FacesException(ex); } } return result; } /** *

The same as newThing except that a single argument constructor * that accepts a Class is looked for before calling the no-arg version.

* *

PRECONDITIONS: the values in the Map are either Strings * representing fully qualified java class names, or java.lang.Class * instances.

*

ALGORITHM: Look in the argument map for a value for the argument * key. If found, if the value is instanceof String, assume the String * specifies a fully qualified java class name and obtain the * java.lang.Class instance for that String using Util.loadClass(). * Replace the String instance in the argument map with the Class * instance. If the value is instanceof Class, proceed. Assert that the * value is either instanceof java.lang.Class or java.lang.String.

*

Now that you have a java.lang.class, call its newInstance and * return it as the result of this method.

* * @param key Used to look up the value in the Map. * @param map The Map that will be searched. * @param targetClass the target class for the single argument ctor * @return The new object instance. */ protected Object newConverter(Class key, Map,Object> map, Class targetClass) { assert (key != null && map != null); Object result = null; Class clazz; Object value; value = map.get(key); if (value == null) { return null; } assert (value instanceof String || value instanceof Class); if (value instanceof String) { String cValue = (String) value; try { clazz = Util.loadClass(cValue, value); if (!associate.isDevModeEnabled()) { map.put(key, clazz); } assert (clazz != null); } catch (Exception e) { throw new FacesException(e.getMessage(), e); } } else { clazz = (Class) value; } Constructor ctor = ReflectionUtils.lookupConstructor(clazz, Class.class); Throwable cause = null; if (ctor != null) { try { result = ctor.newInstance(targetClass); } catch (Exception e) { cause = e; } } else { try { result = clazz.newInstance(); } catch (Exception e) { cause = e; } } if (null != cause) { throw new FacesException((MessageUtils.getExceptionMessageString( MessageUtils.CANT_INSTANTIATE_CLASS_ERROR_MESSAGE_ID, clazz.getName())), cause); } return result; } // --------------------------------------------------------- Private Methods public static final String THIS_LIBRARY = "com.sun.faces.composite.this.library"; private UIComponent createComponentFromScriptResource(FacesContext context, Resource scriptComponentResource, Resource componentResource) { UIComponent result = null; String className = scriptComponentResource.getResourceName(); int lastDot = className.lastIndexOf('.'); className = className.substring(0, lastDot); try { Class componentClass = (Class) componentMap.get(className); if (componentClass == null) { componentClass = Util.loadClass(className, this); } if (!associate.isDevModeEnabled()) { componentMap.put(className, componentClass); } result = (UIComponent) componentClass.newInstance(); } catch (IllegalAccessException ex) { if (LOGGER.isLoggable(Level.SEVERE)) { LOGGER.log(Level.SEVERE, null, ex); } } catch (InstantiationException ex) { if (LOGGER.isLoggable(Level.SEVERE)) { LOGGER.log(Level.SEVERE, null, ex); } } catch (ClassNotFoundException ex) { if (LOGGER.isLoggable(Level.SEVERE)) { LOGGER.log(Level.SEVERE, null, ex); } } if (result != null) { // Make sure the resource is there for the annotation processor. result.getAttributes().put(Resource.COMPONENT_RESOURCE_KEY, componentResource); // In case there are any "this" references, // make sure they can be resolved. context.getAttributes().put(THIS_LIBRARY, componentResource.getLibraryName()); try { associate.getAnnotationManager() .applyComponentAnnotations(context, result); } finally { context.getAttributes().remove(THIS_LIBRARY); } } return result; } /** * Leveraged by {@link Application#createComponent(String)} and {@link Application#createComponent(javax.faces.context.FacesContext, String, String)} * This method will apply any component and render annotations that may be present. */ private UIComponent createComponentApplyAnnotations(FacesContext ctx, String componentType, String rendererType, boolean applyAnnotations) { UIComponent c; try { c = (UIComponent) newThing(componentType, componentMap); } catch (Exception ex) { if (LOGGER.isLoggable(Level.SEVERE)) { LOGGER.log(Level.SEVERE, "jsf.cannot_instantiate_component_error", componentType); } throw new FacesException(ex); } if (c == null) { Object[] params = {componentType}; if (LOGGER.isLoggable(Level.SEVERE)) { LOGGER.log(Level.SEVERE, "jsf.cannot_instantiate_component_error", params); } throw new FacesException(MessageUtils.getExceptionMessageString( MessageUtils.NAMED_OBJECT_NOT_FOUND_ERROR_MESSAGE_ID, params)); } if (LOGGER.isLoggable(Level.FINE)) { LOGGER.log(Level.FINE, MessageFormat.format("Created component with component type of ''{0}''", componentType)); } if (applyAnnotations) { applyAnnotations(ctx, rendererType, c); } return c; } /** * Leveraged by {@link Application#createComponent(javax.el.ValueExpression, javax.faces.context.FacesContext, String)} and * {@link Application#createComponent(javax.el.ValueExpression, javax.faces.context.FacesContext, String, String)}. * This method will apply any component and render annotations that may be present. */ private UIComponent createComponentApplyAnnotations(FacesContext ctx, ValueExpression componentExpression, String componentType, String rendererType, boolean applyAnnotations) { UIComponent c; try { c = (UIComponent) componentExpression .getValue(ctx.getELContext()); if (c == null) { c = this.createComponentApplyAnnotations(ctx, componentType, rendererType, applyAnnotations); componentExpression.setValue((ctx.getELContext()), c); } } catch (Exception ex) { throw new FacesException(ex); } return c; } /** * Process any annotations associated with this component/renderer. */ private void applyAnnotations(FacesContext ctx, String rendererType, UIComponent c) { if (c != null && ctx != null) { associate.getAnnotationManager() .applyComponentAnnotations(ctx, c); if (rendererType != null) { RenderKit rk = ctx.getRenderKit(); Renderer r = null; if (rk != null) { r = rk.getRenderer(c.getFamily(), rendererType); if (r != null) { c.setRendererType(rendererType); associate.getAnnotationManager() .applyRendererAnnotations(ctx, r, c); } } if (rk == null || r == null) { if (LOGGER.isLoggable(Level.FINE)) { LOGGER.log(Level.FINE, "Unable to create Renderer with rendererType {0} for component with component type of {1}", new Object[] { rendererType, c.getFamily() }); } } } } } /** * @return the SystemEventListeners that should be used for the * provided combination of SystemEvent and source. */ private Set getListeners(Class systemEvent, Class sourceClass) { Set listeners = null; EventInfo sourceInfo = systemEventHelper.getEventInfo(systemEvent, sourceClass); if (sourceInfo != null) { listeners = sourceInfo.getListeners(); } return listeners; } private SystemEvent invokeViewListenersFor(FacesContext ctx, Class systemEventClass, SystemEvent event, Object source) { SystemEvent result = event; if (listenerInvocationGuard.isGuardSet(ctx, systemEventClass)) { return result; } listenerInvocationGuard.setGuard(ctx, systemEventClass); UIViewRoot root = ctx.getViewRoot(); try { if (root != null) { List listeners = root.getViewListenersForEventClass(systemEventClass); if (null == listeners) { return null; } EventInfo rootEventInfo = systemEventHelper.getEventInfo(systemEventClass, UIViewRoot.class); // process view listeners result = processListenersAccountingForAdds(listeners, event, source, rootEventInfo); } } finally { listenerInvocationGuard.clearGuard(ctx, systemEventClass); } return result; } /* * This class encapsulates the behavior to prevent infinite loops * when the publishing of one event leads to the queueing of another * event of the same type. Special provision is made to allow the * case where this guaring mechanims happens on a per-FacesContext, * per-SystemEvent.class type basis. */ private ReentrantLisneterInvocationGuard listenerInvocationGuard = new ReentrantLisneterInvocationGuard(); private class ReentrantLisneterInvocationGuard { public boolean isGuardSet(FacesContext ctx, Class systemEventClass) { Boolean result = false; Map, Boolean> data = getDataStructure(ctx); result = data.get(systemEventClass); return (null == result ? false : result); } public void setGuard(FacesContext ctx, Class systemEventClass) { Map, Boolean> data = getDataStructure(ctx); data.put(systemEventClass, Boolean.TRUE); } public void clearGuard(FacesContext ctx, Class systemEventClass) { Map, Boolean> data = getDataStructure(ctx); data.put(systemEventClass, Boolean.FALSE); } private Map, Boolean> getDataStructure(FacesContext ctx) { Map, Boolean> result = null; Map ctxMap = ctx.getAttributes(); final String IS_PROCESSING_LISTENERS_KEY = "com.sun.faces.application.ApplicationImpl.IS_PROCESSING_LISTENERS"; if (null == (result = (Map, Boolean>) ctxMap.get(IS_PROCESSING_LISTENERS_KEY))) { result = new HashMap, Boolean>(12); ctxMap.put(IS_PROCESSING_LISTENERS_KEY, result); } return result; } } /** * @return process any listeners for the specified SystemEventListenerHolder * and return any SystemEvent that may have been created as a side-effect * of processing the listeners. */ private SystemEvent invokeComponentListenersFor(Class systemEventClass, Object source) { if (source instanceof SystemEventListenerHolder) { List listeners = ((SystemEventListenerHolder) source).getListenersForEventClass(systemEventClass); if (null == listeners) { return null; } EventInfo eventInfo = compSysEventHelper.getEventInfo(systemEventClass, source.getClass()); return processListeners(listeners, null, source, eventInfo); } return null; } /** * Traverse the List of listeners and invoke any that are relevent * for the specified source. * * @throws javax.faces.event.AbortProcessingException propagated from the listener invocation */ private SystemEvent invokeListenersFor(Class systemEventClass, SystemEvent event, Object source, Class sourceBaseType, boolean useSourceLookup) throws AbortProcessingException { EventInfo eventInfo = systemEventHelper.getEventInfo(systemEventClass, source, sourceBaseType, useSourceLookup); if (eventInfo != null) { Set listeners = eventInfo.getListeners(); event = processListeners(listeners, event, source, eventInfo); } return event; } /** * Iterate through and invoke the listeners. If the passed event was * null, create the event, and return it. */ private SystemEvent processListeners(Collection listeners, SystemEvent event, Object source, EventInfo eventInfo) { if (listeners != null && !listeners.isEmpty()) { for (SystemEventListener curListener : listeners) { if (curListener != null && curListener.isListenerForSource(source)) { if (event == null) { event = eventInfo.createSystemEvent(source); } assert (event != null); if (event.isAppropriateListener(curListener)) { event.processListener(curListener); } } } } return event; } private SystemEvent processListenersAccountingForAdds(List listeners, SystemEvent event, Object source, EventInfo eventInfo) { if (listeners != null && !listeners.isEmpty()) { // copy listeners // go thru copy completely // compare copy to original // if original differs from copy, make a new copy. // The new copy consists of the original list - processed SystemEventListener listenersCopy[] = new SystemEventListener[listeners.size()]; int i = 0; for (i = 0; i < listenersCopy.length; i++) { listenersCopy[i] = listeners.get(i); } Map processedListeners = new HashMap(listeners.size()); boolean processedSomeEvents = false, originalDiffersFromCopy = false; do { i = 0; originalDiffersFromCopy = false; if (0 < listenersCopy.length) { for (i = 0; i < listenersCopy.length; i++) { SystemEventListener curListener = listenersCopy[i]; if (curListener != null && curListener.isListenerForSource(source)) { if (event == null) { event = eventInfo.createSystemEvent(source); } assert (event != null); if (!processedListeners.containsKey(curListener) && event.isAppropriateListener(curListener)) { processedSomeEvents = true; event.processListener(curListener); processedListeners.put(curListener, Boolean.TRUE); } } } if (originalDiffersFromCopy(listeners, listenersCopy)) { originalDiffersFromCopy = true; listenersCopy = copyListWithExclusions(listeners, processedListeners); } } } while (originalDiffersFromCopy && processedSomeEvents); } return event; } private boolean originalDiffersFromCopy(Collection original, SystemEventListener copy[]) { boolean foundDifference = false; int i = 0, originalLen = original.size(), copyLen = copy.length; if (originalLen == copyLen) { SystemEventListener originalItem, copyItem; Iterator iter = original.iterator(); while (iter.hasNext() && !foundDifference) { originalItem = iter.next(); copyItem = copy[i++]; foundDifference = originalItem != copyItem; } } else { foundDifference = true; } return foundDifference; } private SystemEventListener [] copyListWithExclusions(Collection original, Map excludes) { SystemEventListener [] result = null, temp = new SystemEventListener[original.size()]; int i = 0; for (SystemEventListener cur : original) { if (!excludes.containsKey(cur)) { temp[i++] = cur; } } result = new SystemEventListener[i]; System.arraycopy(temp, 0, result, 0, i); temp = null; return result; } private boolean needsProcessing(FacesContext context, Class systemEventClass) { return context.isProcessingEvents() || ExceptionQueuedEvent.class.isAssignableFrom(systemEventClass); } // ----------------------------------------------------------- Inner Classes /** * Utility class for dealing with application events. */ private static class SystemEventHelper { private final Cache, SystemEventInfo> systemEventInfoCache; // -------------------------------------------------------- Constructors public SystemEventHelper() { systemEventInfoCache = new Cache, SystemEventInfo>( new Factory, SystemEventInfo>() { public SystemEventInfo newInstance(final Class arg) throws InterruptedException { return new SystemEventInfo(arg); } } ); } // ------------------------------------------------------ Public Methods public EventInfo getEventInfo(Class systemEventClass, Class sourceClass) { EventInfo info = null; SystemEventInfo systemEventInfo = systemEventInfoCache.get(systemEventClass); if (systemEventInfo != null) { info = systemEventInfo.getEventInfo(sourceClass); } return info; } public EventInfo getEventInfo(Class systemEventClass, Object source, Class sourceBaseType, boolean useSourceForLookup) { Class sourceClass = ((useSourceForLookup) ? ((sourceBaseType != null) ? sourceBaseType : source.getClass()) : Void.class); return getEventInfo(systemEventClass, sourceClass); } } // END SystemEventHelper /** * Utility class for dealing with {@link javax.faces.component.UIComponent} events. */ private static class ComponentSystemEventHelper { private Cache,Cache,EventInfo>> sourceCache; // -------------------------------------------------------- Constructors public ComponentSystemEventHelper() { // Initialize the 'sources' cache for, ahem, readability... // ~generics++ Factory, Cache, EventInfo>> eventCacheFactory = new Factory, Cache, EventInfo>>() { public Cache, EventInfo> newInstance( final Class sourceClass) throws InterruptedException { Factory, EventInfo> eventInfoFactory = new Factory, EventInfo>() { public EventInfo newInstance(final Class systemEventClass) throws InterruptedException { return new EventInfo(systemEventClass, sourceClass); } }; return new Cache, EventInfo>(eventInfoFactory); } }; sourceCache = new Cache,Cache,EventInfo>>(eventCacheFactory); } // ------------------------------------------------------ Public Methods public EventInfo getEventInfo(Class systemEvent, Class sourceClass) { Cache, EventInfo> eventsCache = sourceCache.get(sourceClass); return eventsCache.get(systemEvent); } } // END ComponentSystemEventHelper /** * Simple wrapper class for application level SystemEvents. It provides the * structure to map a single SystemEvent to multiple sources which are * represented by SourceInfo instances. */ private static class SystemEventInfo { private Cache,EventInfo> cache = new Cache,EventInfo>( new Factory, EventInfo>() { public EventInfo newInstance(Class arg) throws InterruptedException { return new EventInfo(systemEvent, arg); } } ); private Class systemEvent; // -------------------------------------------------------- Constructors private SystemEventInfo(Class systemEvent) { this.systemEvent = systemEvent; } // ------------------------------------------------------ Public Methods public EventInfo getEventInfo(Class source) { Class sourceClass = ((source == null) ? Void.class : source); return cache.get(sourceClass); } } // END SystemEventInfo /** * Represent a logical association between a SystemEvent and a Source. * This call will contain the Listeners specific to this association * as well as provide a method to construct new SystemEvents as required. */ private static class EventInfo { private Class systemEvent; private Class sourceClass; private Set listeners; private Constructor eventConstructor; private Map,Constructor> constructorMap; // -------------------------------------------------------- Constructors public EventInfo(Class systemEvent, Class sourceClass) { this.systemEvent = systemEvent; this.sourceClass = sourceClass; this.listeners = new CopyOnWriteArraySet(); this.constructorMap = new HashMap,Constructor>(); if (!sourceClass.equals(Void.class)) { eventConstructor = getEventConstructor(sourceClass); } } // ------------------------------------------------------ Public Methods public Set getListeners() { return listeners; } public SystemEvent createSystemEvent(Object source) { Constructor toInvoke = getCachedConstructor(source.getClass()); if (toInvoke != null) { try { return (SystemEvent) toInvoke.newInstance(source); } catch (Exception e) { throw new FacesException(e); } } return null; } // ----------------------------------------------------- Private Methods private Constructor getCachedConstructor(Class source) { if (eventConstructor != null) { return eventConstructor; } else { Constructor c = constructorMap.get(source); if (c == null) { c = getEventConstructor(source); if (c != null) { constructorMap.put(source, c); } } return c; } } private Constructor getEventConstructor(Class source) { Constructor ctor = null; try { return systemEvent.getDeclaredConstructor(source); } catch (NoSuchMethodException ignored) { Constructor[] ctors = systemEvent.getConstructors(); if (ctors != null) { for (Constructor c : ctors) { Class[] params = c.getParameterTypes(); if (params.length != 1) { continue; } if (params[0].isAssignableFrom(source)) { return c; } } } if (eventConstructor == null) { if (LOGGER.isLoggable(Level.FINE)) { LOGGER.log(Level.FINE, "Unable to find Constructor within {0} that accepts {1} instances.", new Object[] { systemEvent.getName(), sourceClass.getName() }); } } } return ctor; } } // END SourceInfo private static final class ComponentResourceClassNotFound { } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy