jakarta.faces.application.Application Maven / Gradle / Ivy
Show all versions of jakarta.faces Show documentation
/*
* Copyright (c) 1997, 2021 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the
* Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
* version 2 with the GNU Classpath Exception, which is available at
* https://www.gnu.org/software/classpath/license.html.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
*/
package jakarta.faces.application;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.Locale;
import java.util.Map;
import java.util.ResourceBundle;
import jakarta.el.ELContextListener;
import jakarta.el.ELException;
import jakarta.el.ELResolver;
import jakarta.el.ExpressionFactory;
import jakarta.el.ValueExpression;
import jakarta.faces.FacesException;
import jakarta.faces.component.UIComponent;
import jakarta.faces.component.behavior.Behavior;
import jakarta.faces.component.search.SearchExpressionHandler;
import jakarta.faces.component.search.SearchKeywordResolver;
import jakarta.faces.context.FacesContext;
import jakarta.faces.convert.Converter;
import jakarta.faces.event.ActionListener;
import jakarta.faces.event.SystemEvent;
import jakarta.faces.event.SystemEventListener;
import jakarta.faces.flow.FlowHandler;
import jakarta.faces.validator.Validator;
import jakarta.faces.view.ViewDeclarationLanguage;
/**
*
* Application represents a per-web-application singleton object where applications based
* on Jakarta Faces (or implementations wishing to provide extended functionality) can register application-wide
* singletons that provide functionality required by Jakarta Faces. Default implementations of each object are
* provided for cases where the application does not choose to customize the behavior.
*
*
*
* The instance of {@link Application} is created by calling the getApplication()
method of
* {@link ApplicationFactory}. Because this instance is shared, it must be implemented in a thread-safe manner.
*
*
*
* The application also acts as a factory for several types of Objects specified in the Faces Configuration file. Please
* see {@link Application#createComponent}, {@link Application#createConverter}, and
* {@link Application#createValidator}.
*
*/
public abstract class Application {
private Application defaultApplication;
// ------------------------------------------------------------- Properties
/**
*
* Return the default {@link ActionListener} to be registered for all
* {@link jakarta.faces.component.ActionSource} components in this application. If not explicitly set, a default
* implementation must be provided that performs the functions as specified in the
* section 7.1.1 "ActionListener Property" in the chapter 7 "Application Integration" of the Jakarta Faces Specification Document.
*
*
*
* Note that the specification for the default ActionListener
contiues to call for the use of a
* deprecated property (action
) and class (MethodBinding
). Unfortunately,
* this is necessary because the default ActionListener
must continue to work with components that do not
* implement {@link jakarta.faces.component.ActionSource}, and only implement
* {@link jakarta.faces.component.ActionSource}.
*
*
* @return the action listener.
*/
public abstract ActionListener getActionListener();
/**
*
* Set the default {@link ActionListener} to be registered for all {@link jakarta.faces.component.ActionSource}
* components.
*
*
* @param listener The new default {@link ActionListener}
*
* @throws NullPointerException if listener
is null
*/
public abstract void setActionListener(ActionListener listener);
/**
*
* Return the default Locale
for this application. If not explicitly set, null
is returned.
*
*
* @return the default Locale, or null
.
*/
public abstract Locale getDefaultLocale();
/**
*
* Set the default Locale
for this application.
*
*
* @param locale The new default Locale
*
* @throws NullPointerException if locale
is null
*/
public abstract void setDefaultLocale(Locale locale);
/**
*
* Return the renderKitId
to be used for rendering this application. If not explicitly set,
* null
is returned.
*
*
* @return the default render kit id, or null
.
*/
public abstract String getDefaultRenderKitId();
/**
*
* Set the renderKitId
to be used to render this application. Unless the client has provided a custom
* {@link ViewHandler} that supports the use of multiple {@link jakarta.faces.render.RenderKit} instances in the same
* application, this method must only be called at application startup, before any Faces requests have been processed.
* This is a limitation of the current Specification, and may be lifted in a future release.
*
*
* @param renderKitId the render kit id to set.
*/
public abstract void setDefaultRenderKitId(String renderKitId);
/**
*
* Return the fully qualified class name of the ResourceBundle
to be used for Jakarta Faces messages
* for this application. If not explicitly set, null
is returned.
*
*
* @return the message bundle class name, or null
.
*/
public abstract String getMessageBundle();
/**
*
* Set the fully qualified class name of the ResourceBundle
to be used for Jakarta Faces messages
* for this application. See the JavaDocs for the java.util.ResourceBundle
class for more information about
* the syntax for resource bundle names.
*
*
* @param bundle Base name of the resource bundle to be used
*
* @throws NullPointerException if bundle
is null
*/
public abstract void setMessageBundle(String bundle);
/**
*
* Return the {@link NavigationHandler} instance that will be passed the outcome returned by any invoked application
* action for this web application. If not explicitly set, a default implementation must be provided that performs the
* functions described in the {@link NavigationHandler} class description.
*
*
*
*
* - The
NavigationHandler
implementation is declared in the application configuration resources by
* giving the fully qualified class name as the value of the <navigation-handler>
element within the
* <application>
element.
*
*
* The runtime must employ the decorator pattern as for every other pluggable artifact in Jakarta Faces.
*
*
*
* @return the navigation handler.
*/
public abstract NavigationHandler getNavigationHandler();
/**
*
* Set the {@link NavigationHandler} instance that will be passed the outcome returned by any invoked application action
* for this web application.
*
*
* @param handler The new {@link NavigationHandler} instance
*
* @throws NullPointerException if handler
is null
*/
public abstract void setNavigationHandler(NavigationHandler handler);
/**
*
* Return the singleton, stateless, thread-safe {@link ResourceHandler} for this application. The Jakarta Faces
* implementation must support the following techniques for declaring an alternate implementation of
* ResourceHandler
.
*
*
*
* -
*
* The ResourceHandler
implementation is declared in the application configuration resources by giving the
* fully qualified class name as the value of the <resource-handler>
element within the
* <application>
element.
*
*
*
*
* In all of the above cases, the runtime must employ the decorator pattern as for every other pluggable artifact in
* Jakarta Faces.
*
*
*
* A default implementation is provided that throws UnsupportedOperationException
so that users that
* decorate Application
can continue to function
*
* .
*
*
*
*
* @return the resource handler.
* @since 2.0
*/
public ResourceHandler getResourceHandler() {
if (defaultApplication != null) {
return defaultApplication.getResourceHandler();
}
throw new UnsupportedOperationException();
}
/**
*
* Set the {@link ResourceHandler} instance that will be utilized for rendering the markup for resources, and for
* satisfying client requests to serve up resources.
*
*
* @param resourceHandler The new ResourceHandler
instance
*
* @throws IllegalStateException if this method is called after at least one request has been processed by the
* Lifecycle
instance for this application.
* @throws NullPointerException if resourceHandler
is null
* @since 2.0
*/
public void setResourceHandler(ResourceHandler resourceHandler) {
if (defaultApplication != null) {
defaultApplication.setResourceHandler(resourceHandler);
} else {
throw new UnsupportedOperationException();
}
}
/**
*
* Find a ResourceBundle
as defined in the application configuration resources under the specified name. If
* a ResourceBundle
was defined for the name, return an instance that uses the locale of the current
* {@link jakarta.faces.component.UIViewRoot}.
*
*
*
* The default implementation throws UnsupportedOperationException
and is provided for the sole purpose of
* not breaking existing applications that extend this class.
*
*
* @param ctx the Faces context.
* @param name the name of the resource bundle.
* @return the resource bundle.
* @throws FacesException if a bundle was defined, but not resolvable
* @throws NullPointerException if ctx == null || name == null
* @since 1.2
*/
public ResourceBundle getResourceBundle(FacesContext ctx, String name) {
if (defaultApplication != null) {
return defaultApplication.getResourceBundle(ctx, name);
}
throw new UnsupportedOperationException();
}
/**
*
* Return the project stage for the currently running application instance. The default value is
* {@link ProjectStage#Production}
*
*
*
*
* The implementation of this method must perform the following algorithm or an equivalent with the same end result to
* determine the value to return.
*
*
*
*
*
* If the value has already been determined by a previous call to this method, simply return that value.
*
*
*
* Look for a JNDI
environment entry under the key given by the value of
* {@link ProjectStage#PROJECT_STAGE_JNDI_NAME} (return type of java.lang.String
). If found, continue with
* the algorithm below, otherwise, look for an entry in the initParamMap
of the
* ExternalContext
from the current FacesContext
with the key given by the value of
* {@link ProjectStage#PROJECT_STAGE_PARAM_NAME}
*
*
*
*
* If a value is found, see if an enum constant can be obtained by calling ProjectStage.valueOf()
, passing
* the value from the initParamMap
. If this succeeds without exception, save the value and return it.
*
*
*
* If not found, or any of the previous attempts to discover the enum constant value have failed, log a descriptive
* error message, assign the value as ProjectStage.Production
and return it.
*
*
*
*
*
* A default implementation is provided that throws UnsupportedOperationException
so that users that
* decorate Application
can continue to function
*
* .
*
*
*
* @return the project stage.
* @since 2.0
*/
public ProjectStage getProjectStage() {
if (defaultApplication != null) {
return defaultApplication.getProjectStage();
}
return ProjectStage.Production;
}
/**
*
* Cause an the argument resolver
to be added to the
* resolver chain as specified in section 5.3.2 "ELResolver" of the Jakarta Faces Specification Document.
*
*
*
* It is not possible to remove an ELResolver
registered with this method, once it has been registered.
*
*
*
* It is illegal to register an ELResolver
after the application has received any requests from the client.
* If an attempt is made to register a listener after that time, an IllegalStateException
must be thrown.
* This restriction is in place to allow the Jakarta Server Pages container to optimize for the common case where no
* additional ELResolver
s are in the chain, aside from the standard ones. It is permissible to add
* ELResolver
s before or after initialization to a CompositeELResolver
that is already in the
* chain.
*
*
*
* The default implementation throws UnsupportedOperationException
and is provided for the sole purpose of
* not breaking existing applications that extend {@link Application}.
*
*
* @param resolver the Jakarta Expression Language resolver to add.
*
* @throws IllegalStateException if called after the first request to the
* {@link jakarta.faces.webapp.FacesServlet} has been serviced.
*
* @since 1.2
*/
public void addELResolver(ELResolver resolver) {
if (defaultApplication != null) {
defaultApplication.addELResolver(resolver);
} else {
throw new UnsupportedOperationException();
}
}
/**
*
* Return the singleton {@link ELResolver} instance to be used for all Jakarta Expression Language resolution. This is
* actually an instance of {@link jakarta.el.CompositeELResolver} that must contain the following
* ELResolver
instances in the following order:
*
*
*
*
* -
*
* ELResolver
instances declared using the <el-resolver> element in the application configuration
* resources.
*
*
*
* -
*
* An implementation
that wraps the head of the legacy VariableResolver
chain, as per section
* VariableResolver ChainWrapper in Chapter 5 in the spec document.
*
*
*
* -
*
* An implementation
that wraps the head of the legacy PropertyResolver
chain, as per section
* PropertyResolver ChainWrapper in Chapter 5 in the spec document.
*
*
*
* -
*
* Any ELResolver
instances added by calls to {@link #addELResolver}.
*
*
*
*
*
*
* The default implementation throws UnsupportedOperationException
and is provided for the sole purpose of
* not breaking existing applications that extend {@link Application}.
*
*
* @return the Jakarta Expression Language resolver.
* @since 1.2
*/
public ELResolver getELResolver() {
if (defaultApplication != null) {
return defaultApplication.getELResolver();
}
throw new UnsupportedOperationException();
}
/**
*
* Return the thread-safe singleton {@link FlowHandler} for this application. For implementations declaring compliance
* with version 2.2 of the specification, this method must never return {@code null}, even if the application has no
* flows. This is necessary to enable dynamic flow creation during the application's lifetime.
*
*
*
*
*
* All implementations that declare compliance with version 2.2 of the specification must implement this method. For the
* purpose of backward compatibility with environments that extend {@code
* Application} but do not override this method, an implementation is provided that returns {@code null}. Due to the
* decoratable nature of {@code Application}, code calling this method should always check for a {@code null} return.
*
*
*
* @return the flow handler.
* @since 2.2
*/
public FlowHandler getFlowHandler() {
if (defaultApplication != null) {
return defaultApplication.getFlowHandler();
}
return null;
}
/**
*
* Set the {@link FlowHandler} instance used by the {@link NavigationHandler} to satisfy the requirements of the faces
* flows feature.
*
*
* @param newHandler the flow handler to set.
* @throws NullPointerException if newHandler is null
* @throws IllegalStateException if this method is called after at least one request has been processed by the
* {@code Lifecycle} instance for this application.
* @since 2.2
*/
public void setFlowHandler(FlowHandler newHandler) {
if (defaultApplication != null) {
defaultApplication.setFlowHandler(newHandler);
}
}
/**
*
* Return the {@link ViewHandler} instance that will be utilized during the Restore View and Render
* Response phases of the request processing lifecycle. If not explicitly set, a default implementation must be
* provided that performs the functions described in the {@link ViewHandler} description in the Jakarta Faces
* Specification.
*
*
* @return the view handler.
*/
public abstract ViewHandler getViewHandler();
/**
*
* Set the {@link ViewHandler} instance that will be utilized during the Restore View and Render
* Response phases of the request processing lifecycle.
*
*
* @param handler The new {@link ViewHandler} instance
*
* @throws IllegalStateException if this method is called after at least one request has been processed by the
* Lifecycle
instance for this application.
* @throws NullPointerException if handler
is null
*/
public abstract void setViewHandler(ViewHandler handler);
/**
*
* Return the {@link StateManager} instance that will be utilized during the Restore View and Render
* Response phases of the request processing lifecycle. If not explicitly set, a default implementation must be
* provided that performs the functions described in the {@link StateManager} description in the Jakarta Faces
* Specification.
*
*
* @return the state manager.
*/
public abstract StateManager getStateManager();
/**
*
* Set the {@link StateManager} instance that will be utilized during the Restore View and Render
* Response phases of the request processing lifecycle.
*
*
* @param manager The new {@link StateManager} instance
*
* @throws IllegalStateException if this method is called after at least one request has been processed by the
* Lifecycle
instance for this application.
* @throws NullPointerException if manager
is null
*/
public abstract void setStateManager(StateManager manager);
// ------------------------------------------------------- Object Factories
/**
*
* Register a new mapping of behavior id to the name of the corresponding
* {@link Behavior} class. This allows subsequent calls to createBehavior()
to serve as a factory for
* {@link Behavior} instances.
*
*
* @param behaviorId The behavior id to be registered
* @param behaviorClass The fully qualified class name of the corresponding {@link Behavior} implementation
*
* @throws NullPointerException if behaviorId
or behaviorClass
is null
*
* @since 2.0
*/
public void addBehavior(String behaviorId, String behaviorClass) {
if (defaultApplication != null) {
defaultApplication.addBehavior(behaviorId, behaviorClass);
}
}
/**
*
* Instantiate and return a new {@link Behavior} instance of the class specified
* by a previous call to addBehavior()
for the specified behavior id.
*
*
* @param behaviorId The behavior id for which to create and return a new {@link Behavior} instance
* @return the behavior.
* @throws FacesException if the {@link Behavior} cannot be created
* @throws NullPointerException if behaviorId
is null
*/
public Behavior createBehavior(String behaviorId) throws FacesException {
if (defaultApplication != null) {
return defaultApplication.createBehavior(behaviorId);
}
return null;
}
/**
*
* Return an Iterator
over the set of currently registered behavior ids for this Application
.
*
*
* @return an iterator with behavior ids.
*/
public Iterator getBehaviorIds() {
if (defaultApplication != null) {
return defaultApplication.getBehaviorIds();
}
return Collections.emptyList().iterator();
}
/**
*
* Register a new mapping of component type to the name of the corresponding {@link UIComponent} class. This allows
* subsequent calls to createComponent()
to serve as a factory for {@link UIComponent} instances.
*
*
* @param componentType The component type to be registered
* @param componentClass The fully qualified class name of the corresponding {@link UIComponent} implementation
*
* @throws NullPointerException if componentType
or componentClass
is null
*/
public abstract void addComponent(String componentType, String componentClass);
/**
*
* Instantiate and return a new {@link UIComponent} instance of the class
* specified by a previous call to addComponent()
for the specified component type.
*
*
*
* Before the component instance is returned, it must be inspected for the presence of a
* {@link jakarta.faces.event.ListenerFor} (or {@link jakarta.faces.event.ListenersFor}) or {@link ResourceDependency}
* (or {@link ResourceDependencies}) annotation. If any of these annotations are present, the action listed in
* {@link jakarta.faces.event.ListenerFor} or {@link ResourceDependency} must be taken on the component, before it is
* returned from this method. This variant of createComponent
must not inspect the
* {@link jakarta.faces.render.Renderer} for the component to be returned for any of the afore mentioned annotations.
* Such inspection is the province of {@link #createComponent(ValueExpression, FacesContext, String, String)} or
* {@link #createComponent(FacesContext, String, String)}.
*
*
* @param componentType The component type for which to create and return a new {@link UIComponent} instance
* @return the UI component.
* @throws FacesException if a {@link UIComponent} of the specified type cannot be created
* @throws NullPointerException if componentType
is null
*/
public abstract UIComponent createComponent(String componentType) throws FacesException;
/**
*
* Call the getValue()
method on the specified
* {@link ValueExpression}. If it returns a {@link UIComponent} instance, return it as the value of this method. If it
* does not, instantiate a new {@link UIComponent} instance of the specified component type, pass the new component to
* the setValue()
method of the specified {@link ValueExpression}, and return it.
*
*
*
* Before the component instance is returned, it must be inspected for the presence of a
* {@link jakarta.faces.event.ListenerFor} (or {@link jakarta.faces.event.ListenersFor}) or {@link ResourceDependency}
* (or {@link ResourceDependencies}) annotation. If any of these annotations are present, the action listed in
* {@link jakarta.faces.event.ListenerFor} or {@link ResourceDependency} must be taken on the component, before it is
* returned from this method. This variant of createComponent
must not inspect the
* {@link jakarta.faces.render.Renderer} for the component to be returned for any of the afore mentioned annotations.
* Such inspection is the province of {@link #createComponent(ValueExpression, FacesContext, String, String)} or
* {@link #createComponent(FacesContext, String, String)}.
*
*
*
* A default implementation is provided that throws UnsupportedOperationException
so that users that
* decorate Application
can continue to function.
*
*
* @param componentExpression {@link ValueExpression} representing a component value expression (typically specified by
* the component
attribute of a custom tag)
* @param context {@link FacesContext} for the current request
* @param componentType Component type to create if the {@link ValueExpression} does not return a component instance
* @return the UI component.
* @throws FacesException if a {@link UIComponent} cannot be created
* @throws NullPointerException if any parameter is null
* @since 1.2
*/
public UIComponent createComponent(ValueExpression componentExpression, FacesContext context, String componentType) throws FacesException {
if (defaultApplication != null) {
return defaultApplication.createComponent(componentExpression, context, componentType);
}
throw new UnsupportedOperationException();
}
/**
*
* Like {@link #createComponent(ValueExpression, FacesContext, String)} except the Renderer
for the
* component to be returned must be inspected for the annotations mentioned in
* {@link #createComponent(ValueExpression, FacesContext, String)} as specified in the documentation for that method.
* The Renderer
instance to inspect must be obtained by calling {@link FacesContext#getRenderKit} and
* calling {@link jakarta.faces.render.RenderKit#getRenderer} on the result, passing the argument
* componentType
as the first argument and the result of calling {@link UIComponent#getFamily} on the newly
* created component as the second argument. If no such Renderer
can be found, a message must be logged
* with a helpful error message. Otherwise, {@link UIComponent#setRendererType} must be called on the newly created
* UIComponent
instance, passing the argument rendererType
as the argument.
*
*
*
* A default implementation is provided that throws UnsupportedOperationException
so that users that
* decorate Application
can continue to function.
*
*
*
* @param componentExpression {@link ValueExpression} representing a component value expression (typically specified by
* the component
attribute of a custom tag)
* @param context {@link FacesContext} for the current request
* @param componentType Component type to create if the {@link ValueExpression} does not return a component instance
* @param rendererType The renderer-type of the Renderer
that will render this component. A
* null
value must be accepted for this parameter.
* @return the UI component.
* @throws FacesException if a {@link UIComponent} cannot be created
* @throws NullPointerException if any of the parameters componentExpression
, context
, or
* componentType
are null
* @since 2.0
*/
public UIComponent createComponent(ValueExpression componentExpression, FacesContext context, String componentType, String rendererType) {
if (defaultApplication != null) {
return defaultApplication.createComponent(componentExpression, context, componentType, rendererType);
}
throw new UnsupportedOperationException();
}
/**
*
* Like {@link #createComponent(String)} except the Renderer
for the component to be returned must be
* inspected for the annotations mentioned in {@link #createComponent(ValueExpression, FacesContext, String)} as
* specified in the documentation for that method. The Renderer
instance to inspect must be obtained by
* calling {@link FacesContext#getRenderKit} and calling {@link jakarta.faces.render.RenderKit#getRenderer} on the
* result, passing the argument componentType
as the first argument and the result of calling
* {@link UIComponent#getFamily} on the newly created component as the second argument. If no such Renderer
* can be found, a message must be logged with a helpful error message. Otherwise, {@link UIComponent#setRendererType}
* must be called on the newly created UIComponent
instance, passing the argument rendererType
* as the argument.
*
*
*
* A default implementation is provided that throws UnsupportedOperationException
so that users that
* decorate Application
can continue to function
*
* .
*
*
* @param context {@link FacesContext} for the current request
* @param componentType Component type to create
* @param rendererType The renderer-type of the Renderer
that will render this component. A
* null
value must be accepted for this parameter.
* @return the UI component.
* @throws FacesException if a {@link UIComponent} cannot be created
* @throws NullPointerException if any of the parameters context
, or componentType
are
* null
* @since 2.0
*/
public UIComponent createComponent(FacesContext context, String componentType, String rendererType) {
if (defaultApplication != null) {
return defaultApplication.createComponent(context, componentType, rendererType);
}
throw new UnsupportedOperationException();
}
/**
*
* Instantiate and return a new {@link UIComponent} instance from the
* argument {@link Resource}. An algorithm semantically equivalent to the following must be followed to instantiate the
* UIComponent
to return.
*
*
*
*
*
*
* -
*
* Obtain a reference to the {@link ViewDeclarationLanguage} for this Application
instance by calling
* {@link ViewHandler#getViewDeclarationLanguage}, passing the viewId
found by calling
* {@link jakarta.faces.component.UIViewRoot#getViewId} on the {@link jakarta.faces.component.UIViewRoot} in the
* argument {@link FacesContext}.
*
*
*
*
* -
*
* Obtain a reference to the composite component metadata for this composite component by calling
* {@link ViewDeclarationLanguage#getComponentMetadata}, passing the facesContext
and
* componentResource
arguments to this method. This version of the Jakarta Faces Specification uses
* JavaBeans as the API to the component metadata.
*
*
*
* -
*
* Determine if the component author declared a componentType
for this component instance by obtaining the
* BeanDescriptor
from the component metadata and calling its getValue()
method, passing
* {@link UIComponent#COMPOSITE_COMPONENT_TYPE_KEY} as the argument. If non-null
, the result must be a
* ValueExpression
whose value is the component-type
of the UIComponent
to be
* created for this Resource
component. Call through to {@link #createComponent(java.lang.String)} to
* create the component.
*
*
*
* -
*
* Otherwise, determine if a script based component for this Resource
can be found by calling
* {@link ViewDeclarationLanguage#getScriptComponentResource}. If the result is non-null
, and is a script
* written in a language satisfying the content type text/javascript
, create a
* UIComponent
instance from the script resource.
*
*
*
* -
*
* Otherwise, let library-name be the return from calling {@link Resource#getLibraryName} on the argument
* componentResource
and resource-name be the return from calling {@link Resource#getResourceName}
* on the argument componentResource
. Create a fully qualified Java class name by removing any file
* extension from resource-name and let fqcn be library-name + "." +
resource-name
. If a class with the name of fqcn cannot be found, take no action and continue
* to the next step. If any of InstantiationException
, IllegalAccessException
, or
* ClassCastException
are thrown, wrap the exception in a FacesException
and re-throw it. If
* any other exception is thrown, log the exception and continue to the next step.
*
*
*
* -
*
* If none of the previous steps have yielded a UIComponent
instance, call
* {@link #createComponent(java.lang.String)} passing "jakarta.faces.NamingContainer
" as the argument.
*
*
*
* -
*
* Call {@link UIComponent#setRendererType} on the UIComponent
instance, passing
* "jakarta.faces.Composite
" as the argument.
*
*
*
* -
*
*
* Store the argument Resource
in the attributes Map
of the UIComponent
under the
* key, {@link Resource#COMPONENT_RESOURCE_KEY}.
*
*
*
*
* -
*
*
* Store composite component metadata in the attributes Map
of the UIComponent
under
* the key, {@link UIComponent#BEANINFO_KEY}.
*
*
*
*
*
*
*
* Before the component instance is returned, it must be inspected for the presence of a
* {@link jakarta.faces.event.ListenerFor} annotation. If this annotation is present, the action listed in
* {@link jakarta.faces.event.ListenerFor} must be taken on the component, before it is returned from this method.
*
*
*
* A default implementation is provided that throws UnsupportedOperationException
so that users that
* decorate Application
can continue to function.
*
*
*
*
* @param context {@link FacesContext} for the current request
* @param componentResource A {@link Resource} that points to a source file that provides an implementation of a
* component.
* @return the UI component.
* @throws FacesException if a {@link UIComponent} from the {@link Resource} cannot be created
* @throws NullPointerException if any parameter is null
* @throws NullPointerException if unable, for any reason, to obtain a ViewDeclarationLanguage
instance as
* described above.
* @since 2.0
*/
public UIComponent createComponent(FacesContext context, Resource componentResource) {
if (defaultApplication != null) {
return defaultApplication.createComponent(context, componentResource);
}
throw new UnsupportedOperationException();
}
/**
*
* Return an Iterator
over the set of currently defined component types for this Application
.
*
*
* @return an iterator with component types.
*/
public abstract Iterator getComponentTypes();
/**
*
* Register a new mapping of converter id to the name of the corresponding {@link Converter} class. This allows
* subsequent calls to createConverter()
to serve as a factory for {@link Converter} instances.
*
*
* @param converterId The converter id to be registered
* @param converterClass The fully qualified class name of the corresponding {@link Converter} implementation
*
* @throws NullPointerException if converterId
or converterClass
is null
*/
public abstract void addConverter(String converterId, String converterClass);
/**
*
* Register a new converter class that is capable of performing conversions for the specified target class.
*
*
* @param targetClass The class for which this converter is registered
* @param converterClass The fully qualified class name of the corresponding {@link Converter} implementation
*
* @throws NullPointerException if targetClass
or converterClass
is null
*/
public abstract void addConverter(Class> targetClass, String converterClass);
/**
*
* Instantiate and return a new {@link Converter} instance of the class
* specified by a previous call to addConverter()
for the specified converter id.
*
*
*
* If the toLowerCase()
of the String
represenation of the value of the
* "jakarta.faces.DATETIMECONVERTER_DEFAULT_TIMEZONE_IS_SYSTEM_TIMEZONE
" application configuration
* parameter is "true
" (without the quotes) and the Converter
instance to be returned is an
* instance of {@link jakarta.faces.convert.DateTimeConverter},
* {@link jakarta.faces.convert.DateTimeConverter#setTimeZone} must be called, passing the return from
* TimeZone.getDefault()
.
*
*
*
* The argument converter
must be inspected for the presence of the
* {@link jakarta.faces.application.ResourceDependency} annotation. If the ResourceDependency
annotation is
* present, the action described in ResourceDependency
must be taken. If the
* ResourceDependency
annotation is not present, the argument converter
must be inspected for
* the presence of the {@link jakarta.faces.application.ResourceDependencies} annotation. If the
* ResourceDependencies
annotation is present, the action described in ResourceDependencies
* must be taken.
*
*
* @param converterId The converter id for which to create and return a new {@link Converter} instance
* @return the converter.
* @throws FacesException if the {@link Converter} cannot be created
* @throws NullPointerException if converterId
is null
*/
public abstract Converter createConverter(String converterId);
/**
*
* Instantiate and return a new {@link Converter} instance of the class that
* has registered itself as capable of performing conversions for objects of the specified type. If no such
* {@link Converter} class can be identified, return null
.
*
*
*
* To locate an appropriate {@link Converter} class, the following algorithm is performed, stopping as soon as an
* appropriate {@link Converter} class is found:
*
*
* - Locate a {@link Converter} registered for the target class itself.
* - Locate a {@link Converter} registered for interfaces that are implemented by the target class (directly or
* indirectly).
* - Locate a {@link Converter} registered for the superclass (if any) of the target class, recursively working up the
* inheritance hierarchy.
*
*
*
* If the Converter
has a single argument constructor that accepts a Class
, instantiate the
* Converter
using that constructor, passing the argument targetClass
as the sole argument.
* Otherwise, simply use the zero-argument constructor.
*
*
*
* If the toLowerCase()
of the String
represenation of the value of the
* "jakarta.faces.DATETIMECONVERTER_DEFAULT_TIMEZONE_IS_SYSTEM_TIMEZONE
" application configuration
* parameter is "true
" (without the quotes) and the Converter
instance to be returned is an
* instance of {@link jakarta.faces.convert.DateTimeConverter},
* {@link jakarta.faces.convert.DateTimeConverter#setTimeZone} must be called, passing the return from
* TimeZone.getDefault()
.
*
*
* @param targetClass Target class for which to return a {@link Converter}
* @return the converter.
* @throws FacesException if the {@link Converter} cannot be created
* @throws NullPointerException if targetClass
is null
*/
public abstract Converter createConverter(Class> targetClass);
/**
*
* Return an Iterator
over the set of currently registered converter ids for this Application
.
*
*
* @return an iterator with converter ids.
*/
public abstract Iterator getConverterIds();
/**
*
* Return an Iterator
over the set of Class
instances for which {@link Converter} classes have
* been explicitly registered.
*
*
* @return an iterator with converter types.
*/
public abstract Iterator> getConverterTypes();
/**
*
* Register a validator by its id that is applied to all UIInput
components in a view. The validator to
* most often serve this role is the BeanValidator
. The usage contract for this method assumes that the
* validator has been registered using the normal “by-id” registration mechanism.
*
*
*
* An implementation is provided that takes no action so that users that decorate the Application
continue
* to work.
*
* @param validatorId the validator id.
* @since 2.0
*/
public void addDefaultValidatorId(String validatorId) {
if (defaultApplication != null) {
defaultApplication.addDefaultValidatorId(validatorId);
}
}
/**
*
* Return an immutable Map
over the set of currently registered default validator IDs and their class name
* for this Application
.
*
*
*
* An implementation is provided that returns Collections.emptyMap
so that users that decorate the
* Application
continue to work.
*
* @return a map of default validator information.
* @since 2.0
*/
public Map getDefaultValidatorInfo() {
if (defaultApplication != null) {
return defaultApplication.getDefaultValidatorInfo();
}
return Collections.emptyMap();
}
/**
*
* Return the {@link ExpressionFactory} instance for this application. This instance is used by the convenience method
* {@link #evaluateExpressionGet}.
*
*
*
* The implementation must return the ExpressionFactory
from the Expression Language container by calling
* jakarta.el.ELManager.getExpressionFactory()
.
*
*
*
* An implementation is provided that throws UnsupportedOperationException
so that users that decorate the
* Application
continue to work.
*
* @return the expression factory.
* @since 1.2
*/
public ExpressionFactory getExpressionFactory() {
if (defaultApplication != null) {
return defaultApplication.getExpressionFactory();
}
throw new UnsupportedOperationException();
}
/**
*
* Get a value by evaluating an expression.
*
*
*
* Call {@link #getExpressionFactory} then call {@link ExpressionFactory#createValueExpression} passing the argument
* expression
and expectedType
. Call {@link FacesContext#getELContext} and pass it to
* {@link ValueExpression#getValue}, returning the result.
*
*
*
* An implementation is provided that throws UnsupportedOperationException
so that users that decorate the
* Application
continue to work.
*
* @param the return type.
* @param context the Faces context.
* @param expression the expression.
* @param expectedType the expected type.
* @return the result of the evaluation.
*/
public T evaluateExpressionGet(FacesContext context, String expression, Class extends T> expectedType) throws ELException {
if (defaultApplication != null) {
return defaultApplication.evaluateExpressionGet(context, expression, expectedType);
}
throw new UnsupportedOperationException();
}
/**
*
* Return an Iterator
over the supported Locale
s for this appication.
*
*
* @return an iterator of the supported locales.
*/
public abstract Iterator getSupportedLocales();
/**
*
* Set the Locale
instances representing the supported Locale
s for this application.
*
*
* @param locales The set of supported Locale
s for this application
*
* @throws NullPointerException if the argument newLocales
is null
.
*
*/
public abstract void setSupportedLocales(Collection locales);
/**
*
* Provide a way for Faces applications to register an ELContextListener
that will be notified on creation
* of ELContext
instances. This listener will be called once per request.
*
*
*
* An implementation is provided that throws UnsupportedOperationException
so that users that decorate the
* Application
continue to work.
*
* @param listener the Jakarta Expression Language context listener to add.
* @since 1.2
*/
public void addELContextListener(ELContextListener listener) {
if (defaultApplication != null) {
defaultApplication.addELContextListener(listener);
} else {
throw new UnsupportedOperationException();
}
}
/**
*
* Remove the argument listener
from the list of {@link ELContextListener}s. If listener
is
* null, no exception is thrown and no action is performed. If listener
is not in the list, no exception is
* thrown and no action is performed.
*
*
*
* An implementation is provided that throws UnsupportedOperationException
so that users that decorate the
* Application
continue to work.
*
* @param listener the Jakarta Expression Language context listener to remove.
* @since 1.2
*/
public void removeELContextListener(ELContextListener listener) {
if (defaultApplication != null) {
defaultApplication.removeELContextListener(listener);
} else {
throw new UnsupportedOperationException();
}
}
/**
*
* If no calls have been made to {@link #addELContextListener}, this method must return an empty array.
*
*
*
* Otherwise, return an array representing the list of listeners added by calls to {@link #addELContextListener}.
*
*
*
* An implementation is provided that throws UnsupportedOperationException
so that users that decorate the
* Application
continue to work.
*
* @return an array of Jakarta Expression Language context listeners.
* @since 1.2
*/
public ELContextListener[] getELContextListeners() {
if (defaultApplication != null) {
return defaultApplication.getELContextListeners();
}
throw new UnsupportedOperationException();
}
/**
*
* Register a new mapping of validator id to the name of the corresponding {@link Validator} class. This allows
* subsequent calls to createValidator()
to serve as a factory for {@link Validator} instances.
*
*
* @param validatorId The validator id to be registered
* @param validatorClass The fully qualified class name of the corresponding {@link Validator} implementation
*
* @throws NullPointerException if validatorId
or validatorClass
is null
*/
public abstract void addValidator(String validatorId, String validatorClass);
/**
*
* Instantiate and return a new {@link Validator} instance of the class
* specified by a previous call to addValidator()
for the specified validator id.
*
*
*
* The argument validator
must be inspected for the presence of the
* {@link jakarta.faces.application.ResourceDependency} annotation. If the ResourceDependency
annotation is
* present, the action described in ResourceDependency
must be taken. If the
* ResourceDependency
annotation is not present, the argument validator
must be inspected for
* the presence of the {@link jakarta.faces.application.ResourceDependencies} annotation. If the
* ResourceDependencies
annotation is present, the action described in ResourceDependencies
* must be taken.
*
*
* @param validatorId The validator id for which to create and return a new {@link Validator} instance
* @return the validator.
* @throws FacesException if a {@link Validator} of the specified id cannot be created
* @throws NullPointerException if validatorId
is null
*/
public abstract Validator createValidator(String validatorId) throws FacesException;
/**
*
* Return an Iterator
over the set of currently registered validator ids for this Application
.
*
*
* @return an iterator of validator ids.
*/
public abstract Iterator getValidatorIds();
/**
*
* If {@link jakarta.faces.context.FacesContext#isProcessingEvents()} is true
and there are one or more
* listeners for events of the type represented by systemEventClass
, call those listeners, passing
* source
as the source of the event. The implementation should be as fast as possible in determining
* whether or not a listener for the given systemEventClass
and source
has been installed, and
* should return immediately once such a determination has been made. The implementation of publishEvent
* must honor the requirements stated in {@link #subscribeToEvent} regarding the storage and retrieval of listener
* instances. Specifically, if {@link #subscribeToEvent(Class,Class,SystemEventListener)} was called, the
* sourceClass
argument must match exactly the Class
of the source
argument in
* the call to publishEvent()
. The implementation must not do any inheritance hierarachy inspection when
* looking for a match between the sourceClass
passed to
* {@link #subscribeToEvent(Class,Class,SystemEventListener)} and the sourceClass
passed to
* publishEvent()
in order to find any listeners to which the event should be published. In the case where
* the Class
of the source
argument does not match the Class
of the
* sourceClass
used when the listener was subscribed using subscribeToEvent()
,
* {@link #publishEvent(FacesContext,Class,Class,Object)} can be used to provide the Class
used to perform
* the listener lookup and match.
*
*
*
*
*
* The default implementation must implement an algorithm semantically equivalent to the following to locate listener
* instances and to invoke them.
*
*
*
*
* -
*
* If the source
argument implements {@link jakarta.faces.event.SystemEventListenerHolder}, call
* {@link jakarta.faces.event.SystemEventListenerHolder#getListenersForEventClass} on it, passing the
* systemEventClass
argument. If the list is not empty, perform algorithm traverseListenerList on
* the list.
*
*
*
* -
*
* If any view level listeners have been installed by previous calls to
* {@link #subscribeToEvent(Class, Class, jakarta.faces.event.SystemEventListener)} on the
* {@link jakarta.faces.component.UIViewRoot}, perform algorithm traverseListenerList on the list of listeners
* for that event installed on the UIViewRoot
.
*
*
*
* -
*
* If any Application
level listeners have been installed by previous calls to
* {@link #subscribeToEvent(Class, Class, jakarta.faces.event.SystemEventListener)}, perform algorithm
* traverseListenerList on the list.
*
*
*
* -
*
* If any Application
level listeners have been installed by previous calls to
* {@link #subscribeToEvent(Class, jakarta.faces.event.SystemEventListener)}, perform algorithm
* traverseListenerList on the list.
*
*
*
*
*
*
* If the act of invoking the processListener
method causes an
* {@link jakarta.faces.event.AbortProcessingException} to be thrown, processing of the listeners must be aborted, no
* further processing of the listeners for this event must take place, and the exception must be logged with
* Level.SEVERE
.
*
*
*
* Algorithm traverseListenerList: For each listener in the list,
*
*
*
*
* -
*
* Call {@link jakarta.faces.event.SystemEventListener#isListenerForSource}, passing the source
argument.
* If this returns false
, take no action on the listener.
*
*
*
* -
*
* Otherwise, if the event to be passed to the listener instances has not yet been constructed, construct the event,
* passing source
as the argument to the one-argument constructor that takes an Object
. This
* same event instance must be passed to all listener instances.
*
*
*
* -
*
* Call {@link jakarta.faces.event.SystemEvent#isAppropriateListener}, passing the listener instance as the argument. If
* this returns false
, take no action on the listener.
*
*
*
* -
*
* Call {@link jakarta.faces.event.SystemEvent#processListener}, passing the listener instance.
*
*
*
*
*
*
* A default implementation is provided that throws UnsupportedOperationException
so that users that
* decorate Application
can continue to function
*
* .
*
*
*
* @param context the FacesContext
for the current request
* @param systemEventClass The Class
of event that is being published.
* @param source The source for the event of type systemEventClass
.
*
* @throws NullPointerException if either context
, systemEventClass
or source
is
* null
*
* @since 2.0
*
*/
public void publishEvent(FacesContext context, Class extends SystemEvent> systemEventClass, Object source) {
if (defaultApplication != null) {
defaultApplication.publishEvent(context, systemEventClass, source);
} else {
throw new UnsupportedOperationException();
}
}
/**
*
* This method functions exactly like {@link #publishEvent(FacesContext,Class,Object)}, except the run-time must use the
* argument sourceBaseType
to find the matching listener instead of using the Class
of the
* source
argument.
*
*
*
* A default implementation is provided that throws UnsupportedOperationException
so that users that
* decorate Application
can continue to function
*
* .
*
* @param context the FacesContext
for the current request
* @param systemEventClass The Class
of event that is being published.
* @param sourceBaseType The Class
of the source event that must be used to lookup the listener to which
* this event must be published. If this argument is null
the return from source.getClass()
* must be used as the sourceBaseType
.
* @param source The source for the event of type systemEventClass
.
*
* @throws NullPointerException if any arguments except for sourceBaseType
are null
*
* @since 2.0
*/
public void publishEvent(FacesContext context, Class extends SystemEvent> systemEventClass, Class> sourceBaseType, Object source) {
if (defaultApplication != null) {
defaultApplication.publishEvent(context, systemEventClass, sourceBaseType, source);
} else {
throw new UnsupportedOperationException();
}
}
/**
*
* Install the listener instance referenced by argument listener
* into the application as a listener for events of type systemEventClass
that originate from objects of
* type sourceClass
.
*
*
*
*
*
* If argument sourceClass
is non-null
, sourceClass
and
* systemEventClass
must be used to store the argument listener
in the application in such a
* way that the listener
can be quickly looked up by the implementation of {@link #publishEvent} given
* systemEventClass
and an instance of the Class
referenced by sourceClass
. If
* argument sourceClass
is null
, the listener
must be discoverable by the
* implementation of {@link #publishEvent} given only systemEventClass
.
*
*
*
*
*
*
*
* It is valid to call this method during the processing of an event which was subscribed to by a
* previous call to this method.
*
*
*
*
*
* @param systemEventClass the Class
of event for which listener
must be fired.
*
* @param sourceClass the Class
of the instance which causes events of type systemEventClass
* to be fired. May be null
.
*
* @param listener the implementation of {@link jakarta.faces.event.SystemEventListener} whose
* {@link jakarta.faces.event.SystemEventListener#processEvent} method must be called when events of type
* systemEventClass
are fired.
*
* @throws NullPointerException if any combination of systemEventClass
, or listener
are
* null
.
*
* @since 2.0
*/
public void subscribeToEvent(Class extends SystemEvent> systemEventClass, Class> sourceClass, SystemEventListener listener) {
if (defaultApplication != null) {
defaultApplication.subscribeToEvent(systemEventClass, sourceClass, listener);
} else {
throw new UnsupportedOperationException();
}
}
/**
*
* Install the listener instance referenced by argument listener
* into application as a listener for events of type systemEventClass
. The default implementation simply
* calls through to {@link #subscribeToEvent(Class, Class, jakarta.faces.event.SystemEventListener)} passing
* null
as the sourceClass
argument
*
*
*
* A default implementation is provided that throws UnsupportedOperationException
so that users that
* decorate Application
can continue to function
*
* .
*
* @param systemEventClass the Class
of event for which listener
must be fired.
*
* @param listener the implementation of {@link jakarta.faces.event.SystemEventListener} whose
* {@link jakarta.faces.event.SystemEventListener#processEvent} method must be called when events of type
* systemEventClass
are fired.
*
*
*
*
* See {@link #subscribeToEvent(java.lang.Class,java.lang.Class,jakarta.faces.event.SystemEventListener)} for an
* additional requirement regarding when it is valid to call this method.
*
*
*
*
* @throws NullPointerException if any combination of systemEventClass
, or listener
are
* null
.
*
* @since 2.0
*/
public void subscribeToEvent(Class extends SystemEvent> systemEventClass, SystemEventListener listener) {
if (defaultApplication != null) {
defaultApplication.subscribeToEvent(systemEventClass, listener);
} else {
throw new UnsupportedOperationException();
}
}
/**
*
* Remove the listener instance referenced by argument listener
* from the application as a listener for events of type systemEventClass
that originate from objects of
* type sourceClass
. See {@link #subscribeToEvent(Class, Class, jakarta.faces.event.SystemEventListener)}
* for the specification of how the listener is stored, and therefore, how it must be removed.
*
*
*
*
*
* See {@link #subscribeToEvent(java.lang.Class,java.lang.Class,jakarta.faces.event.SystemEventListener)} for an
* additional requirement regarding when it is valid to call this method.
*
*
*
*
* @param systemEventClass the Class
of event for which listener
must be fired.
*
* @param sourceClass the Class
of the instance which causes events of type systemEventClass
* to be fired. May be null
.
*
* @param listener the implementation of {@link jakarta.faces.event.SystemEventListener} to remove from the internal
* data structure.
*
* @throws NullPointerException if any combination of systemEventClass
, or
* listener
are null
.
*
* @since 2.0
*/
public void unsubscribeFromEvent(Class extends SystemEvent> systemEventClass, Class> sourceClass, SystemEventListener listener) {
if (defaultApplication != null) {
defaultApplication.unsubscribeFromEvent(systemEventClass, sourceClass, listener);
} else {
throw new UnsupportedOperationException();
}
}
/**
*
* Remove the listener instance referenced by argument listener
* from the application as a listener for events of type systemEventClass
. The default implementation
* simply calls through to {@link #unsubscribeFromEvent(Class, jakarta.faces.event.SystemEventListener)} passing
* null
as the sourceClass
argument
*
*
*
*
*
* See {@link #subscribeToEvent(java.lang.Class,java.lang.Class,jakarta.faces.event.SystemEventListener)} for an
* additional requirement regarding when it is valid to call this method.
*
*
*
*
* @param systemEventClass the Class
of event for which listener
must be fired.
*
* @param listener the implementation of {@link jakarta.faces.event.SystemEventListener} to remove from the internal
* data structure.
*
* @throws NullPointerException if any combination of systemEventClass
, or
* listener
are null
.
*
* @since 2.0
*/
public void unsubscribeFromEvent(Class extends SystemEvent> systemEventClass, SystemEventListener listener) {
if (defaultApplication != null) {
defaultApplication.unsubscribeFromEvent(systemEventClass, listener);
} else {
throw new UnsupportedOperationException();
}
}
/**
*
* Return the thread-safe singleton {@link SearchExpressionHandler} for this application.
*
*
* @return the {@link SearchExpressionHandler}.
* @since 2.3
*/
public SearchExpressionHandler getSearchExpressionHandler() {
if (defaultApplication != null) {
return defaultApplication.getSearchExpressionHandler();
}
throw new UnsupportedOperationException();
}
/**
*
* Set the {@link SearchExpressionHandler} instance used by the application.
*
*
* @param searchExpressionHandler the {@link SearchExpressionHandler}.
* @throws NullPointerException if searchExpressionHandler is null
* @throws IllegalStateException if this method is called after at least one request has been processed by the
* {@code Lifecycle} instance for this application.
*
* @since 2.3
*/
public void setSearchExpressionHandler(SearchExpressionHandler searchExpressionHandler) {
if (defaultApplication != null) {
defaultApplication.setSearchExpressionHandler(searchExpressionHandler);
} else {
throw new UnsupportedOperationException();
}
}
/**
*
* Cause the argument resolver
to be added to the head of the resolver chain.
*
*
*
*
*
* It is not possible to remove a {@link SearchKeywordResolver} registered with this method, once it has been
* registered.
*
*
*
* The default implementation throws UnsupportedOperationException
and is provided for the sole purpose of
* not breaking existing applications that extend {@link Application}.
*
*
*
*
* @param resolver the SearchKeywordResolver to add.
*
* @throws IllegalStateException if called after the first request to the {@link jakarta.faces.webapp.FacesServlet} has
* been serviced.
* @throws NullPointerException when resolver is null.
*
* @since 2.3
*/
public void addSearchKeywordResolver(SearchKeywordResolver resolver) {
if (defaultApplication != null) {
defaultApplication.addSearchKeywordResolver(resolver);
} else {
throw new UnsupportedOperationException();
}
}
/**
*
* Return the singleton {@link SearchKeywordResolver} instance to be used for all search keyword resolution. This is
* actually an instance of a composite SearchKeywordResolver that must contain the following
* SearchKeywordResolver
instances in the following order:
*
*
*
*
* -
*
* SearchKeywordResolver
instances declared using the <search-keyword-resolver> element in the
* application configuration resources.
*
*
*
* -
*
* Any SearchKeywordResolver
instances added by calls to {@link #addSearchKeywordResolver}.
*
*
*
* -
*
* The SearchKeywordResolver
implementations for @all
, @child(n)
,
* @form
, @id(...)
, @namingcontainer
, @next
, @none
,
* @parent
, @previous
, @root
and @this
.
*
*
*
*
*
*
* The default implementation throws UnsupportedOperationException
and is provided for the sole purpose of
* not breaking existing applications that extend {@link Application}.
*
*
* @return the {@link SearchKeywordResolver}.
* @since 2.3
*/
public SearchKeywordResolver getSearchKeywordResolver() {
if (defaultApplication != null) {
return defaultApplication.getSearchKeywordResolver();
}
throw new UnsupportedOperationException();
}
}