* Set the resource library contracts calculated as valid to use with this view. The implementation must copy the
* contents of the incoming {@code List} into an immutable {@code List} for return from
* {@link #getResourceLibraryContracts}. If the argument is {@code null} or empty, the action taken is the same as if
* the argument is {@code null}: a subsequent call to {@code getResourceLibraryContracts} returns {@code null}. This
* method may only be called during the processing of {@link jakarta.faces.view.ViewDeclarationLanguage#createView} and
* during the VDL tag handler for the tag corresponding to an instance of {@code UIViewRoot}. For backward compatibility
* with implementations of the specification prior to when this method was introduced, an implementation is provided
* that takes no action. Implementations compliant with the version in which this method was introduced must implement
* this method as specified.
*
*
*
* @param contracts The new contracts to be returned, as an immutable {@code List}. from a subsequent call to
* {@link #getResourceLibraryContracts}.
*
* @throws IllegalStateException if this method is called after this instance has been released
*
* @since 2.2
*
*/
public void setResourceLibraryContracts(List contracts) {
}
/**
*
* Return true
if the validationFailed()
method has been called for the current request.
*
*
* @return boolean indicating if the validationFailed()
method has been called for the current request
*
* @throws IllegalStateException if this method is called after this instance has been released
*/
public boolean isValidationFailed() {
if (defaultFacesContext != null) {
return defaultFacesContext.isValidationFailed();
}
throw new UnsupportedOperationException();
}
/**
*
* Return the {@link ResponseStream} to which components should direct their binary output. Within a given response,
* components can use either the ResponseStream or the ResponseWriter, but not both.
*
* @return ResponseStream
instance.
*
* @throws IllegalStateException if this method is called after this instance has been released
*/
public abstract ResponseStream getResponseStream();
/**
*
* Set the {@link ResponseStream} to which components should direct their binary output.
*
* @param responseStream The new ResponseStream for this response
*
* @throws NullPointerException if responseStream
is null
*
* @throws IllegalStateException if this method is called after this instance has been released
*/
public abstract void setResponseStream(ResponseStream responseStream);
/**
*
* Return the {@link ResponseWriter} to which components should direct their character-based output. Within a given
* response, components can use either the ResponseStream or the ResponseWriter, but not both.
*
*
* @return ResponseWriter
instance.
*
* @throws IllegalStateException if this method is called after this instance has been released
*/
public abstract ResponseWriter getResponseWriter();
/**
*
* Set the {@link ResponseWriter} to which components should direct their character-based output.
*
* @param responseWriter The new ResponseWriter for this response
*
* @throws IllegalStateException if this method is called after this instance has been released
* @throws NullPointerException if responseWriter
is null
*/
public abstract void setResponseWriter(ResponseWriter responseWriter);
/**
*
* Return the root component that is associated with the this request.
*
*
*
* It is valid to call this method during application startup or shutdown. If called during application startup or
* shutdown, this method returns a new UIViewRoot
with its locale set to Locale.getDefault()
.
*
*
* @return UIViewRoot
instance.
*
* @throws IllegalStateException if this method is called after this instance has been released
*/
public abstract UIViewRoot getViewRoot();
/**
*
* Set the root component that is associated with this
* request.
*
*
* This method can be called by the application handler (or a class that the handler calls), during the Invoke
* Application phase of the request processing lifecycle and during the Restore View phase of the request
* processing lifecycle (especially when a new root component is created). In the present version of the specification,
* implementations are not required to enforce this restriction, though a future version of the specification may
* require enforcement.
*
*
*
* If the current UIViewRoot
is non-null
, and calling equals()
on the argument
* root
, passing the current UIViewRoot
returns false
, the clear
* method must be called on the Map
returned from {@link UIViewRoot#getViewMap}.
*
*
* @param root The new component {@link UIViewRoot} component
*
* @throws IllegalStateException if this method is called after this instance has been released
* @throws NullPointerException if root
is null
*/
public abstract void setViewRoot(UIViewRoot root);
// ---------------------------------------------------------- Public Methods
/**
*
* Append a {@link jakarta.faces.application.FacesMessage} to the set of messages associated with the specified client
* identifier, if clientId
is not null
. If clientId
is null
, this
* {@link jakarta.faces.application.FacesMessage} is assumed to not be associated with any specific component instance.
*
*
* @param clientId The client identifier with which this message is associated (if any)
* @param message The message to be appended
*
* @throws IllegalStateException if this method is called after this instance has been released
* @throws NullPointerException if message
is null
*/
public abstract void addMessage(String clientId, FacesMessage message);
/**
*
* Return a flag indicating if the resources associated with this FacesContext
instance have been released.
*
*
* @return true
if the resources have been released.
*
* @since 2.1
*/
public boolean isReleased() {
if (defaultFacesContext != null) {
return defaultFacesContext.isReleased();
}
throw new UnsupportedOperationException();
}
/**
*
* Release any resources associated with this FacesContext
* instance. Faces implementations may choose to pool instances in the associated {@link FacesContextFactory} to avoid
* repeated object creation and garbage collection. After release()
is called on a
* FacesContext
instance (until the FacesContext
instance has been recycled by the
* implementation for re-use), calling any other methods will cause an IllegalStateException
to be thrown.
*
*
*
* If a call was made to {@link #getAttributes} during the processing for this request, the implementation must call
* clear()
on the Map
returned from getAttributes()
, and then de-allocate the
* data-structure behind that Map
.
*
*
*
* The implementation must call {@link #setCurrentInstance} passing null
to remove the association between
* this thread and this dead FacesContext
instance.
*
*
* @throws IllegalStateException if this method is called after this instance has been released
*/
public abstract void release();
/**
*
* Signal the Jakarta Faces implementation that, as soon as the current phase of the request processing lifecycle
* has been completed, control should be passed to the Render Response phase, bypassing any phases that have
* not been executed yet.
*
*
* @throws IllegalStateException if this method is called after this instance has been released
*/
public abstract void renderResponse();
/**
*
* This utility method simply returns the result of
* {@link jakarta.faces.render.ResponseStateManager#isPostback(FacesContext)}.
*
*
*
* The default implementation throws UnsupportedOperationException
and is provided for the sole purpose of
* not breaking existing applications that extend this class.
*
*
* @return the boolean indicating whether this request is a post one.
*
* @throws IllegalStateException if this method is called after this instance has been released
*
* @since 2.0
*/
public boolean isPostback() {
if (defaultFacesContext != null) {
return defaultFacesContext.isPostback();
}
throw new UnsupportedOperationException();
}
/**
*
* Signal the Jakarta Faces implementation that the HTTP response for this request has already been generated
* (such as an HTTP redirect), and that the request processing lifecycle should be terminated as soon as the current
* phase is completed.
*
*
* @throws IllegalStateException if this method is called after this instance has been released
*/
public abstract void responseComplete();
/**
*
* Sets a flag which indicates that a conversion or validation error occurred while processing the inputs. Inputs
* consist of either page parameters or form bindings. This flag can be read using {@link #isValidationFailed}.
*
*
* @throws IllegalStateException if this method is called after this instance has been released
*/
public void validationFailed() {
if (defaultFacesContext != null) {
defaultFacesContext.validationFailed();
} else {
throw new UnsupportedOperationException();
}
}
/**
*
* Return the value last set on this FacesContext
instance when {@link #setCurrentPhaseId} was called.
*
*
* @return the current phase id.
*
* @throws IllegalStateException if this method is called after this instance has been released
*
* @since 2.0
*/
public PhaseId getCurrentPhaseId() {
if (defaultFacesContext != null) {
return defaultFacesContext.getCurrentPhaseId();
}
if (!isCreatedFromValidFactory) {
return currentPhaseIdForInvalidFactoryConstruction;
}
throw new UnsupportedOperationException();
}
/**
*
* The implementation must call this method at the earliest possble point in time after entering into a new phase in the
* request processing lifecycle.
*
*
* @param currentPhaseId The {@link jakarta.faces.event.PhaseId} for the current phase.
*
* @throws IllegalStateException if this method is called after this instance has been released
*
* @since 2.0
*/
public void setCurrentPhaseId(PhaseId currentPhaseId) {
if (defaultFacesContext != null) {
defaultFacesContext.setCurrentPhaseId(currentPhaseId);
} else if (!isCreatedFromValidFactory) {
currentPhaseIdForInvalidFactoryConstruction = currentPhaseId;
} else {
throw new UnsupportedOperationException();
}
}
private PhaseId currentPhaseIdForInvalidFactoryConstruction;
/**
*
* Allows control of wheter or not the runtime will publish events when
* {@link Application#publishEvent(FacesContext, Class, Object)} or
* {@link Application#publishEvent(FacesContext, Class, Class, Object)} is called.
*
*
* @param processingEvents flag indicating events should be processed or not
*/
public void setProcessingEvents(boolean processingEvents) {
this.processingEvents = processingEvents;
}
/**
*
* Returns a flag indicating whether or not the runtime should publish events when asked to do so.
*
*
* @return true
if events should be published, otherwise false
*/
public boolean isProcessingEvents() {
return processingEvents;
}
/**
*
* Return true
if the current {@link ProjectStage} as returned by the {@link Application} instance is equal
* to stage
, otherwise return false
*
*
* @param stage the {@link ProjectStage} to check
*
* @return boolean indicating whether the application has the same stage.
*
* @throws IllegalStateException if this method is called after this instance has been released
* @throws NullPointerException if stage
is null
*/
public boolean isProjectStage(ProjectStage stage) {
if (stage == null) {
throw new NullPointerException();
}
return stage.equals(getApplication().getProjectStage());
}
// ---------------------------------------------------------- Static Methods
/**
*
* The ThreadLocal
variable used to record the {@link FacesContext} instance for each processing thread.
*
*/
private static final ThreadLocal instance = ThreadLocal.withInitial(() -> null);
/**
*
* Return the {@link FacesContext} instance for the request that is being processed by the current thread. If called
* during application initialization or shutdown, any method documented as "valid to call this method during application
* startup or shutdown" must be supported during application startup or shutdown time. The result of calling a method
* during application startup or shutdown time that does not have this designation is undefined.
*
*
* @return the instance of FacesContext
.
*/
public static FacesContext getCurrentInstance() {
FacesContext facesContext = instance.get();
if (null == facesContext) {
facesContext = threadInitContext.get(Thread.currentThread());
}
// Bug 20458755: If not found in the threadInitContext, use
// a special FacesContextFactory implementation that knows how to
// use the initContextServletContext map to obtain current ServletContext
// out of thin air (actually, using the current ClassLoader), and use it
// to obtain the init FacesContext corresponding to that ServletContext.
if (null == facesContext) {
// In the non-init case, this will immediately return null.
// In the init case, this will return null if Jakarta Faces hasn't been
// initialized in the ServletContext corresponding to this
// Thread's context ClassLoader.
ClassLoader cl = Thread.currentThread().getContextClassLoader();
if (cl == null) {
return null;
}
FacesContextFactory privateFacesContextFactory = (FacesContextFactory) FactoryFinder.getFactory("com.sun.faces.ServletContextFacesContextFactory");
if (null != privateFacesContextFactory) {
facesContext = privateFacesContextFactory.getFacesContext(null, null, null, null);
}
}
return facesContext;
}
/**
*
* Set the {@link FacesContext} instance for the request that is being processed by the current thread.
*
*
* @param context The {@link FacesContext} instance for the current thread, or null
if this thread no
* longer has a FacesContext
instance.
*
*/
protected static void setCurrentInstance(FacesContext context) {
if (context == null) {
instance.remove();
} else {
instance.set(context);
}
}
}