/* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * * Copyright (c) 1997-2010 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.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 javax.faces.context; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import javax.faces.application.Application; import javax.faces.application.FacesMessage; import javax.faces.application.ProjectStage; import javax.faces.application.FacesMessage.Severity; import javax.faces.component.UIViewRoot; import javax.faces.render.RenderKit; import javax.el.ELContext; import javax.faces.FactoryFinder; import javax.faces.component.UINamingContainer; import javax.faces.event.PhaseId; /** * <p><strong class="changed_modified_2_0 changed_modified_2_1 * changed_modified_2_2">FacesContext</strong> contains all of the * per-request state information related to the processing of a single * JavaServer Faces request, and the rendering of the corresponding * response. It is passed to, and potentially modified by, each phase * of the request processing lifecycle.</p> * * <p>A {@link FacesContext} instance is associated with a particular * request at the beginning of request processing, by a call to the * <code>getFacesContext()</code> method of the {@link FacesContextFactory} * instance associated with the current web application. The instance * remains active until its <code>release()</code> method is called, after * which no further references to this instance are allowed. While a * {@link FacesContext} instance is active, it must not be referenced * from any thread other than the one upon which the servlet container * executing this web application utilizes for the processing of this request. * </p> * * <p class="changed_added_2_3">A FacesContext can be injected into a request * scoped bean using <code>@Inject FacesContext facesContext;</code> * </p> */ public abstract class FacesContext { @SuppressWarnings({"UnusedDeclaration"}) private FacesContext defaultFacesContext; private boolean processingEvents = true; private boolean isCreatedFromValidFactory = true; private static ConcurrentHashMap threadInitContext = new ConcurrentHashMap(2); private static ConcurrentHashMap initContextServletContext = new ConcurrentHashMap(2); public FacesContext() { Thread curThread = Thread.currentThread(); StackTraceElement[] callstack = curThread.getStackTrace(); if (null != callstack) { String declaringClassName = callstack[3].getClassName(); try { ClassLoader curLoader = curThread.getContextClassLoader(); Class declaringClass = curLoader.loadClass(declaringClassName); if (!FacesContextFactory.class.isAssignableFrom(declaringClass)) { isCreatedFromValidFactory = false; } } catch (ClassNotFoundException cnfe) { } } } // -------------------------------------------------------------- Properties /** * <p><span class="changed_modified_2_0">Return</span> the {@link * Application} instance associated with this web application.</p> * <p class="changed_added_2_0">It is valid to call this method * during application startup or shutdown. If called during application * startup or shutdown, returns the correct current {@link * javax.faces.application.Application} instance.</p> * * @return the <code>Application</code> instance associated with this web application. * * @throws IllegalStateException if this method is called after * this instance has been released */ public abstract Application getApplication(); /** * <p class="changed_added_2_0">Return a mutable <code>Map</code> * representing the attributes associated wth this * <code>FacesContext</code> instance. This <code>Map</code> is * useful to store attributes that you want to go out of scope when the * Faces lifecycle for the current request ends, which is not always the same * as the request ending, especially in the case of Servlet filters * that are invoked <strong>after</strong> the Faces lifecycle for this * request completes. Accessing this <code>Map</code> does not cause any * events to fire, as is the case with the other maps: for request, session, and * application scope. When {@link #release()} is invoked, the attributes * must be cleared.</p> * * <div class="changed_added_2_0"> * * <p>The <code>Map</code> returned by this method is not associated with * the request. If you would like to get or set request attributes, * see {@link ExternalContext#getRequestMap}. * * <p>The default implementation throws * <code>UnsupportedOperationException</code> and is provided * for the sole purpose of not breaking existing applications that extend * this class.</p> * * </div> * * @return mutable <code>Map</code> representing the attributes associated wth this * <code>FacesContext</code> instance. * * @throws IllegalStateException if this method is called after * this instance has been released * * @since 2.0 */ public Map<Object, Object> getAttributes() { if (defaultFacesContext != null) { return defaultFacesContext.getAttributes(); } if (!isCreatedFromValidFactory) { if (attributesForInvalidFactoryConstruction == null) { attributesForInvalidFactoryConstruction = new HashMap<>(); } return attributesForInvalidFactoryConstruction; } throw new UnsupportedOperationException(); } private Map<Object, Object> attributesForInvalidFactoryConstruction; /** * <p class="changed_added_2_0">Return the {@link PartialViewContext} * for this request. The {@link PartialViewContext} is used to control * the processing of specified components during the execute portion of * the request processing lifecycle (known as partial processing) and * the rendering of specified components (known as partial rendering). * This method must return a new {@link PartialViewContext} if one * does not already exist.</p> * * @return the instance of <code>PartialViewContext</code> for this request. * * @throws IllegalStateException if this method is called after * this instance has been released * * @since 2.0 */ public PartialViewContext getPartialViewContext() { if (defaultFacesContext != null) { return defaultFacesContext.getPartialViewContext(); } if (!isCreatedFromValidFactory) { if (partialViewContextForInvalidFactoryConstruction == null) { PartialViewContextFactory f = (PartialViewContextFactory) FactoryFinder.getFactory(FactoryFinder.PARTIAL_VIEW_CONTEXT_FACTORY); partialViewContextForInvalidFactoryConstruction = f.getPartialViewContext(FacesContext.getCurrentInstance()); } return partialViewContextForInvalidFactoryConstruction; } throw new UnsupportedOperationException(); } private PartialViewContext partialViewContextForInvalidFactoryConstruction = null; /** * <p>Return an <code>Iterator</code> over the client identifiers for * which at least one {@link javax.faces.application.FacesMessage} has been queued. If there are no * such client identifiers, an empty <code>Iterator</code> is returned. * If any messages have been queued that were not associated with any * specific client identifier, a <code>null</code> value will be included * in the iterated values. The elements in the <code>Iterator</code> must * be returned in the order in which they were added with {@link #addMessage}.</p> * * @return the <code>Iterator</code> over the client identifiers for * which at least one {@link javax.faces.application.FacesMessage} has been queued. * * @throws IllegalStateException if this method is called after * this instance has been released */ public abstract Iterator<String> getClientIdsWithMessages(); /** * <p>Return the <code>ELContext</code> instance for this * <code>FacesContext</code> instance. This <code>ELContext</code> * instance has the same lifetime and scope as the * <code>FacesContext</code> instance with which it is associated, * and may be created lazily the first time this method is called * for a given <code>FacesContext</code> instance. Upon creation of * the ELContext instance, the implementation must take the * following action: </p> * * <ul> * * <li><p>Call the {@link ELContext#putContext} method on the * instance, passing in <code>FacesContext.class</code> and the * <code>this</code> reference for the <code>FacesContext</code> * instance itself.</p></li> * * <li><p>If the <code>Collection</code> returned by {@link * javax.faces.application.Application#getELContextListeners} is * non-empty, create an instance of {@link * javax.el.ELContextEvent} and pass it to each {@link * javax.el.ELContextListener} instance in the * <code>Collection</code> by calling the {@link * javax.el.ELContextListener#contextCreated} method.</p></li> * * </ul> * * @return instance of <code>ELContext</code>. * * @throws IllegalStateException if this method is called after * this instance has been released * * @since 1.2 */ public ELContext getELContext() { if (defaultFacesContext != null) { return defaultFacesContext.getELContext(); } throw new UnsupportedOperationException(); } /** * <p class="changed_added_2_0">Return the {@link ExceptionHandler} * for this request.</p> * * @return instance of <code>ExceptionHandler</code>. */ public ExceptionHandler getExceptionHandler() { if (defaultFacesContext != null) { return defaultFacesContext.getExceptionHandler(); } throw new UnsupportedOperationException(); } /** * <p class="changed_added_2_0">Set the {@link ExceptionHandler} for * this request.</p> * * @param exceptionHandler the <code>ExceptionHandler</code> for * this request. */ public void setExceptionHandler(ExceptionHandler exceptionHandler) { if (defaultFacesContext != null) { defaultFacesContext.setExceptionHandler(exceptionHandler); } else { throw new UnsupportedOperationException(); } } /** * <p><span class="changed_modified_2_0">Return</span> the {@link * ExternalContext} instance for this <code>FacesContext</code> * instance.</p> * <p class="changed_added_2_0">It is valid to call this method * during application startup or shutdown. If called during application * startup or shutdown, this method returns an {@link ExternalContext} instance * with the special behaviors indicated in the javadoc for that * class. Methods document as being valid to call during * application startup or shutdown must be supported.</p> * * @return instance of <code>ExternalContext</code> * * @throws IllegalStateException if this method is called after * this instance has been released */ public abstract ExternalContext getExternalContext(); /** * <p>Return the maximum severity level recorded on any * {@link javax.faces.application.FacesMessage}s that has been queued, whether or not they are * associated with any specific {@link javax.faces.component.UIComponent}. If no such messages * have been queued, return <code>null</code>.</p> * * @return the maximum severity level. * * @throws IllegalStateException if this method is called after * this instance has been released */ public abstract Severity getMaximumSeverity(); /** * <p>Return an <code>Iterator</code> over the {@link javax.faces.application.FacesMessage}s * that have been queued, whether or not they are associated with any * specific client identifier. If no such messages have been queued, * return an empty <code>Iterator</code>. The elements of the <code>Iterator</code> * must be returned in the order in which they were added with calls to {@link * #addMessage}.</p> * * @return <code>Iterator</code> over the <code>FacesMessage</code>s * that have been queued. * * @throws IllegalStateException if this method is called after * this instance has been released */ public abstract Iterator<FacesMessage> getMessages(); /** * <p class="changed_added_2_0">Like {@link #getMessages}, but * returns a <code>List<FacesMessage></code>, * enabling use from EL expressions.</p> * * <p>The default implementation throws * <code>UnsupportedOperationException</code> and is provided * for the sole purpose of not breaking existing applications that extend * this class.</p> * * @return an immutable <code>List</code> which is effectively a snapshot * of the messages present at the time of invocation. * * @throws IllegalStateException if this method is called after * this instance has been released * * @since 2.0 */ public List<FacesMessage> getMessageList() { if (defaultFacesContext != null) { return defaultFacesContext.getMessageList(); } throw new UnsupportedOperationException(); } /** * <p class="changed_added_2_0">Like {@link * #getMessages(java.lang.String)}, but returns a * <code>List<FacesMessage></code> of messages for the * component with client id matching argument * <code>clientId</code>.</p> * * <p>The default implementation throws * <code>UnsupportedOperationException</code> and is provided * for the sole purpose of not breaking existing applications that extend * this class.</p> * * @param clientId the client id of a component. * * @return an immutable <code>List</code> which is effectively a snapshot * of the messages present at the time of invocation. * * @throws IllegalStateException if this method is called after * this instance has been released * * @since 2.0 */ public List<FacesMessage> getMessageList(String clientId) { if (defaultFacesContext != null) { return defaultFacesContext.getMessageList(clientId); } throw new UnsupportedOperationException(); } /** * <p>Return an <code>Iterator</code> over the {@link javax.faces.application.FacesMessage}s that * have been queued that are associated with the specified client identifier * (if <code>clientId</code> is not <code>null</code>), or over the * {@link javax.faces.application.FacesMessage}s that have been queued that are not associated with * any specific client identifier (if <code>clientId</code> is * <code>null</code>). If no such messages have been queued, return an * empty <code>Iterator</code>. The elements of the <code>Iterator</code> * must be returned in the order in which they were added with calls to {@link * #addMessage}.</p> * * @param clientId The client identifier for which messages are * requested, or <code>null</code> for messages not associated with * any client identifier * * @return <code>Iterator</code> over the <code>FacesMessage</code>s. * * @throws IllegalStateException if this method is called after * this instance has been released */ public abstract Iterator<FacesMessage> getMessages(String clientId); /** * <p class="changed_added_2_2">Return the result of calling {@link * UINamingContainer#getSeparatorChar}, passing <code>this</code> as * the argument. Note that this enables accessing the value of this * property from the EL expression * <code>#{facesContext.namingContainerSeparatorChar}</code>.</p> * * @return the separator char. * */ public char getNamingContainerSeparatorChar() { return UINamingContainer.getSeparatorChar(this); } /** * <p>Return the {@link RenderKit} instance for the render kit identifier * specified on our {@link UIViewRoot}, if there is one. If there is no * current {@link UIViewRoot}, if the {@link UIViewRoot} does not have a * specified <code>renderKitId</code>, or if there is no {@link RenderKit} * for the specified identifier, return <code>null</code> instead.</p> * * @return instance of <code>RenderKit</code> associated with the <code>UIViewRoot</code>. * * @throws IllegalStateException if this method is called after * this instance has been released */ public abstract RenderKit getRenderKit(); /** * <p>Return <code>true</code> if the <code>renderResponse()</code> * method has been called for the current request.</p> * * @return flag indicating whether the <code>renderResponse()</code> * has been called. * * @throws IllegalStateException if this method is called after * this instance has been released */ public abstract boolean getRenderResponse(); /** * <p>Return <code>true</code> if the <code>responseComplete()</code> * method has been called for the current request.</p> * * @return the boolean indicating whether <code>responseComplete()</code> * method has been called. * * @throws IllegalStateException if this method is called after * this instance has been released */ public abstract boolean getResponseComplete(); /** * <p class="changed_added_2_2">Return the list of resource library * contracts that have been calculated * to be appropriate for use with this view, or an empty list if there are * no such resource library contracts. The list returned by this method * must be immutable. For backward compatibility with implementations * of the specification prior to when this method was introduced, an * implementation is provided that returns an empty list. Implementations * compliant with the version in which this method was introduced must * implement this method as specified.</p> * * @return the list of resource library contracts. * * @throws IllegalStateException if this method is called after * this instance has been released * * @since 2.2 */ public List<String> getResourceLibraryContracts() { return Collections.emptyList(); } /** * <p class="changed_added_2_2">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 javax.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. * * </p> * * @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<String> contracts) { } /** * <p class="changed_added_2_0">Return <code>true</code> if the <code>validationFailed()</code> * method has been called for the current request.</p> * * @return boolean indicating if the <code>validationFailed()</code> * 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(); } /** * <p>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 <code>ResponseStream</code> instance. * * @throws IllegalStateException if this method is called after * this instance has been released */ public abstract ResponseStream getResponseStream(); /** * <p>Set the {@link ResponseStream} to which components should * direct their binary output. * * @param responseStream The new ResponseStream for this response * * @throws NullPointerException if <code>responseStream</code> * is <code>null</code> * * @throws IllegalStateException if this method is called after * this instance has been released */ public abstract void setResponseStream(ResponseStream responseStream); /** * <p>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.</p> * * @return <code>ResponseWriter</code> instance. * * @throws IllegalStateException if this method is called after * this instance has been released */ public abstract ResponseWriter getResponseWriter(); /** * <p>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 <code>responseWriter</code> * is <code>null</code> */ public abstract void setResponseWriter(ResponseWriter responseWriter); /** * <p><span class="changed_modified_2_0">Return</span> the root * component that is associated with the this request. </p> * <p class="changed_added_2_0">It is valid to call this method * during application startup or shutdown. If called during application * startup or shutdown, this method returns a new <code>UIViewRoot</code> with * its locale set to <code>Locale.getDefault()</code>.</p> * * @return <code>UIViewRoot</code> instance. * * @throws IllegalStateException if this method is called after * this instance has been released */ public abstract UIViewRoot getViewRoot(); /** * <p><span class="changed_modified_2_0 * changed_modified_2_1">Set</span> the root component that is * associated with this request. * <p class="changed_modified_2_1">This method can be called by the * application handler (or a class that the handler calls), during * the <em>Invoke Application</em> phase of the request processing * lifecycle and during the <em>Restore View</em> 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.</p> * <p class="changed_added_2_0">If the current * <code>UIViewRoot</code> is non-<code>null</code>, and calling * <code>equals()</code> on the argument <code>root</code>, passing * the current <code>UIViewRoot</code> returns <code>false</code>, * the <code>clear</code> method must be called on the * <code>Map</code> returned from {@link UIViewRoot#getViewMap}.</p> * * @param root The new component {@link UIViewRoot} component * * @throws IllegalStateException if this method is called after * this instance has been released * @throws NullPointerException if <code>root</code> * is <code>null</code> */ public abstract void setViewRoot(UIViewRoot root); // ---------------------------------------------------------- Public Methods /** * <p>Append a {@link javax.faces.application.FacesMessage} to the set of messages associated with * the specified client identifier, if <code>clientId</code> is * not <code>null</code>. If <code>clientId</code> is <code>null</code>, * this {@link javax.faces.application.FacesMessage} is assumed to not be associated with any * specific component instance.</p> * * @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 <code>message</code> * is <code>null</code> */ public abstract void addMessage(String clientId, FacesMessage message); /** * <p class="changed_added_2_1"> * Return a flag indicating if the resources associated with this * <code>FacesContext</code> instance have been released.</p> * @return <code>true</code> if the resources have been released. * * @since 2.1 */ public boolean isReleased() { if (defaultFacesContext != null) { return defaultFacesContext.isReleased(); } throw new UnsupportedOperationException(); } /** * <p><span class="changed_modified_2_0">Release</span> any * resources associated with this <code>FacesContext</code> * instance. Faces implementations may choose to pool instances in * the associated {@link FacesContextFactory} to avoid repeated * object creation and garbage collection. After * <code>release()</code> is called on a <code>FacesContext</code> * instance (until the <code>FacesContext</code> instance has been * recycled by the implementation for re-use), calling any other * methods will cause an <code>IllegalStateException</code> to be * thrown.</p> * <p class="changed_added_2_0">If a call was made to {@link * #getAttributes} during the processing for this request, the * implementation must call <code>clear()</code> on the * <code>Map</code> returned from <code>getAttributes()</code>, and * then de-allocate the data-structure behind that * <code>Map</code>.</p> * <p>The implementation must call {@link #setCurrentInstance} * passing <code>null</code> to remove the association between this * thread and this dead <code>FacesContext</code> instance.</p> * * @throws IllegalStateException if this method is called after * this instance has been released */ public abstract void release(); /** * <p>Signal the JavaServer faces implementation that, as soon as the * current phase of the request processing lifecycle has been completed, * control should be passed to the <em>Render Response</em> phase, * bypassing any phases that have not been executed yet.</p> * * @throws IllegalStateException if this method is called after * this instance has been released */ public abstract void renderResponse(); /** * <p class="changed_added_2_0"> * This utility method simply returns the result of * {@link javax.faces.render.ResponseStateManager#isPostback(FacesContext)}. * </p> * * <p class="changed_added_2_0">The default implementation throws * <code>UnsupportedOperationException</code> and is provided * for the sole purpose of not breaking existing applications that extend * this class.</p> * * @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(); } /** * <p>Signal the JavaServer 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.</p> * * @throws IllegalStateException if this method is called after * this instance has been released */ public abstract void responseComplete(); /** * <p class="changed_added_2_0">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}.</p> * * @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(); } } /** * <p class="changed_added_2_0">Return the value last set on this * <code>FacesContext</code> instance when {@link #setCurrentPhaseId} * was called.</p> * * @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 this.currentPhaseIdForInvalidFactoryConstruction; } throw new UnsupportedOperationException(); } /** * <p class="changed_added_2_0">The implementation must call this method * at the earliest possble point in time after entering into a new phase * in the request processing lifecycle.</p> * * @param currentPhaseId The {@link javax.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) { this.currentPhaseIdForInvalidFactoryConstruction = currentPhaseId; } else { throw new UnsupportedOperationException(); } } private PhaseId currentPhaseIdForInvalidFactoryConstruction; /** * <p class="changed_added_2_0">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.</p> * * @param processingEvents flag indicating events should be processed or not */ public void setProcessingEvents(boolean processingEvents) { this.processingEvents = processingEvents; } /** * <p class="changed_added_2_0">Returns a flag indicating whether or * not the runtime should publish events when asked to do so.</p> * @return <code>true</code> if events should be published, otherwise * <code>false</code> */ public boolean isProcessingEvents() { return this.processingEvents; } /** * <p class="changed_added_2_0">Return <code>true</code> if the * current {@link ProjectStage} as returned by the {@link * Application} instance is equal to <code>stage</code>, otherwise * return <code>false</code></p> * @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 <code>stage</code> is <code>null</code> */ public boolean isProjectStage(ProjectStage stage) { if (stage == null) { throw new NullPointerException(); } return (stage.equals(getApplication().getProjectStage())); } // ---------------------------------------------------------- Static Methods /** * <p>The <code>ThreadLocal</code> variable used to record the * {@link FacesContext} instance for each processing thread.</p> */ private static ThreadLocal<FacesContext> instance = new ThreadLocal<FacesContext>() { @Override protected FacesContext initialValue() { return (null); } }; /** * <p class="changed_modified_2_0">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.</p> * * @return the instance of <code>FacesContext</code>. */ public static FacesContext getCurrentInstance() { FacesContext facesContext = instance.get(); if (null == facesContext) { 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 JSF 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; } /** * <p>Set the {@link FacesContext} instance for the request that is * being processed by the current thread.</p> * * @param context The {@link FacesContext} instance for the current * thread, or <code>null</code> if this thread no longer has a * <code>FacesContext</code> instance. * */ protected static void setCurrentInstance(FacesContext context) { if (context == null) { instance.remove(); } else { instance.set(context); } } }