/*
* Copyright 2017 OmniFaces
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package org.omnifaces.cdi.eager;
import static org.omnifaces.cdi.eager.EagerBeansWebListener.SESSION_CREATED;
import static org.omnifaces.util.Servlets.getRequestRelativeURIWithoutPathParameters;
import java.io.IOException;
import java.util.concurrent.atomic.AtomicBoolean;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequestListener;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionListener;
import org.omnifaces.filter.HttpFilter;
/**
* <p>
* A servlet Filter that can be used as alternative for {@link EagerBeansWebListener}.
* <p>
* This instantiates eager request scoped beans during request processing at the point where this filter
* is inserted in the chain.
* <p>
* This is needed for those situations where the CDI request scope is NOT available in a {@link ServletRequestListener},
* such as is the case for GlassFish 3 (note that this is not spec compliant, CDI request scope should be available) and where
* session scoped beans cannot be instantiated from an {@link HttpSessionListener} such as is the case for GlassFish 3 again.
* <p>
* If this Filter is installed {@link EagerBeansWebListener} main function (instantiating request and session scoped
* beans) will be automatically disabled.
* <p>
* Naturally this filter should not be enabled for environments where CDI is not available at all.
*
* @since 1.8
* @author Arjan Tijms
*
*/
public class EagerBeansFilter extends HttpFilter { // TODO: remove in OmniFaces 3.0
@Override
public void init() throws ServletException {
EagerBeansWebListener.disable();
}
@Override
public void doFilter(HttpServletRequest request, HttpServletResponse response, HttpSession session, FilterChain chain) throws ServletException, IOException {
EagerBeansRepository.getInstance().instantiateByRequestURI(getRequestRelativeURIWithoutPathParameters(request));
chain.doFilter(request, response);
HttpSession newSession = request.getSession(false);
if (newSession != null) {
// Get the session created marker inserted by EagerBeansSessionListener. Note that HttpSession#isNew()
// would be tons easier but doesn't seem to work reliably on all servers.
AtomicBoolean sessionCreated = (AtomicBoolean) newSession.getAttribute(SESSION_CREATED);
if (sessionCreated != null) {
// First remove so session created marker to minimize other threads/request picking it up at all.
newSession.removeAttribute(SESSION_CREATED);
// Even if we remove it immediately there's still a chance for a race, so test the boolean atomically
// and make sure only one thread sees the initial value of "true" returned.
if (sessionCreated.getAndSet(false)) {
EagerBeansRepository.getInstance().instantiateSessionScoped();
}
}
}
}
}