Package org.ocpsoft.rewrite.servlet

Source Code of org.ocpsoft.rewrite.servlet.RewriteFilter

/*
* Copyright 2013 <a href="mailto:lincolnbaxter@gmail.com">Lincoln Baxter, III</a>
*
* 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.ocpsoft.rewrite.servlet;

import java.io.IOException;
import java.util.Collections;
import java.util.List;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

import org.ocpsoft.common.pattern.WeightedComparator;
import org.ocpsoft.common.services.ServiceLoader;
import org.ocpsoft.common.spi.ServiceEnricher;
import org.ocpsoft.common.util.Iterators;
import org.ocpsoft.logging.Logger;
import org.ocpsoft.logging.Logger.Level;
import org.ocpsoft.rewrite.AbstractRewrite;
import org.ocpsoft.rewrite.Version;
import org.ocpsoft.rewrite.config.ConfigurationProvider;
import org.ocpsoft.rewrite.el.spi.ExpressionLanguageProvider;
import org.ocpsoft.rewrite.event.Rewrite;
import org.ocpsoft.rewrite.servlet.event.BaseRewrite;
import org.ocpsoft.rewrite.servlet.event.InboundServletRewrite;
import org.ocpsoft.rewrite.servlet.http.HttpRewriteLifecycleContext;
import org.ocpsoft.rewrite.servlet.impl.HttpRewriteContextImpl;
import org.ocpsoft.rewrite.servlet.spi.ContextListener;
import org.ocpsoft.rewrite.servlet.spi.InboundRewriteProducer;
import org.ocpsoft.rewrite.servlet.spi.OutboundRewriteProducer;
import org.ocpsoft.rewrite.servlet.spi.RequestCycleWrapper;
import org.ocpsoft.rewrite.servlet.spi.RequestListener;
import org.ocpsoft.rewrite.servlet.spi.RequestParameterProvider;
import org.ocpsoft.rewrite.servlet.spi.RewriteLifecycleListener;
import org.ocpsoft.rewrite.servlet.spi.RewriteResultHandler;
import org.ocpsoft.rewrite.spi.ConfigurationCacheProvider;
import org.ocpsoft.rewrite.spi.InvocationResultHandler;
import org.ocpsoft.rewrite.spi.RewriteProvider;
import org.ocpsoft.rewrite.util.ServiceLogger;

/**
* {@link Filter} responsible for handling all inbound {@link org.ocpsoft.rewrite.event.Rewrite} events.
*
* @author <a href="mailto:lincolnbaxter@gmail.com">Lincoln Baxter, III</a>
*/
public class RewriteFilter implements Filter
{
   private static Logger log = Logger.getLogger(RewriteFilter.class);

   private static String FILTER_COUNT_KEY = RewriteFilter.class.getName() + "_FILTER_COUNT";

   private List<RewriteLifecycleListener<Rewrite>> listeners;
   private List<RequestCycleWrapper<ServletRequest, ServletResponse>> wrappers;
   private List<RewriteProvider<ServletContext, Rewrite>> providers;
   private List<RewriteResultHandler> resultHandlers;
   private List<InboundRewriteProducer<ServletRequest, ServletResponse>> inbound;
   private List<OutboundRewriteProducer<ServletRequest, ServletResponse, Object>> outbound;

   private ServletContext servletContext;

   @Override
   @SuppressWarnings("unchecked")
   public void init(final FilterConfig filterConfig) throws ServletException
   {
      if (log.isInfoEnabled())
         log.info("RewriteFilter starting up...");

      servletContext = filterConfig.getServletContext();

      listeners = Iterators.asList(ServiceLoader.load(RewriteLifecycleListener.class));
      wrappers = Iterators.asList(ServiceLoader.load(RequestCycleWrapper.class));
      providers = Iterators.asList(ServiceLoader.load(RewriteProvider.class));
      resultHandlers = Iterators.asList(ServiceLoader.load(RewriteResultHandler.class));
      inbound = Iterators.asList(ServiceLoader.load(InboundRewriteProducer.class));
      outbound = Iterators.asList(ServiceLoader.load(OutboundRewriteProducer.class));

      Collections.sort(listeners, new WeightedComparator());
      Collections.sort(wrappers, new WeightedComparator());
      Collections.sort(providers, new WeightedComparator());
      Collections.sort(resultHandlers, new WeightedComparator());
      Collections.sort(inbound, new WeightedComparator());
      Collections.sort(outbound, new WeightedComparator());

      ServiceLogger.logLoadedServices(log, RewriteLifecycleListener.class, listeners);
      ServiceLogger.logLoadedServices(log, RequestCycleWrapper.class, wrappers);
      ServiceLogger.logLoadedServices(log, RewriteProvider.class, providers);
      ServiceLogger.logLoadedServices(log, RewriteResultHandler.class, resultHandlers);
      ServiceLogger.logLoadedServices(log, InboundRewriteProducer.class, inbound);
      ServiceLogger.logLoadedServices(log, OutboundRewriteProducer.class, outbound);

      /*
       * Log more services for debug purposes only.
       */
      ServiceLogger.logLoadedServices(log, ContextListener.class,
               Iterators.asList(ServiceLoader.load(ContextListener.class)));

      ServiceLogger.logLoadedServices(log, RequestListener.class,
               Iterators.asList(ServiceLoader.load(RequestListener.class)));

      ServiceLogger.logLoadedServices(log, RequestParameterProvider.class,
               Iterators.asList(ServiceLoader.load(RequestParameterProvider.class)));

      ServiceLogger.logLoadedServices(log, ExpressionLanguageProvider.class,
               Iterators.asList(ServiceLoader.load(ExpressionLanguageProvider.class)));

      ServiceLogger.logLoadedServices(log, InvocationResultHandler.class,
               Iterators.asList(ServiceLoader.load(InvocationResultHandler.class)));

      ServiceLogger.logLoadedServices(log, ServiceEnricher.class,
               Iterators.asList(ServiceLoader.load(ServiceEnricher.class)));

      /*
       * Load ConfigurationProviders and ConfigurationCacheProviders here solely so that we
       * can see registered implementations at boot time.
       */
      ServiceLogger.logLoadedServices(log, ConfigurationCacheProvider.class,
               Iterators.asList(ServiceLoader.load(ConfigurationCacheProvider.class)));

      List<ConfigurationProvider<?>> configurations = Iterators.asList(ServiceLoader
               .load(ConfigurationProvider.class));
      ServiceLogger.logLoadedServices(log, ConfigurationProvider.class, configurations);

      for (RewriteProvider<ServletContext, Rewrite> provider : providers) {
         if (provider instanceof ServletRewriteProvider)
            ((ServletRewriteProvider<?>) provider).init(servletContext);
      }

      if ((configurations == null) || configurations.isEmpty())
      {
         if (log.isWarnEnabled())
            log.warn("No ConfigurationProviders were registered: " +
                     "Rewrite will not be enabled on this application. " +
                     "Did you forget to create a '/META-INF/services/" + ConfigurationProvider.class.getName() +
                     " file containing the fully qualified name of your provider implementation?");
      }

      if (log.isInfoEnabled())
         log.info(Version.getFullName() + " initialized.");
   }

   @Override
   public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain)
            throws IOException, ServletException
   {
      InboundServletRewrite<ServletRequest, ServletResponse> event = createRewriteEvent(request,
               response);

      if (event == null)
      {
         if (log.isWarnEnabled())
            log.warn("No Rewrite event was produced - RewriteFilter disabled on this request.");
         chain.doFilter(request, response);
      }
      else
      {
         incrementFilterCount(request);

         if (request.getAttribute(RewriteLifecycleContext.LIFECYCLE_CONTEXT_KEY) == null)
         {
            HttpRewriteLifecycleContext context = new HttpRewriteContextImpl(inbound, outbound, listeners,
                     resultHandlers, wrappers, providers);
            request.setAttribute(RewriteLifecycleContext.LIFECYCLE_CONTEXT_KEY, context);
         }

         for (RewriteLifecycleListener<Rewrite> listener : listeners)
         {
            if (listener.handles(event))
               listener.beforeInboundLifecycle(event);
         }

         for (RequestCycleWrapper<ServletRequest, ServletResponse> wrapper : wrappers)
         {
            if (wrapper.handles(event))
            {
               event.setRequest(wrapper.wrapRequest(event.getRequest(), event.getResponse(), servletContext));
               event.setResponse(wrapper.wrapResponse(event.getRequest(), event.getResponse(), servletContext));
            }
         }

         try {
            rewrite(event);
         }
         catch (ServletException e) {
            if (getFilterCount(request) == 1)
               AbstractRewrite.logEvaluatedRules(event, Level.ERROR);

            decrementFilterCount(request);
            throw e;
         }
         catch (RuntimeException e) {
            if (getFilterCount(request) == 1)
               AbstractRewrite.logEvaluatedRules(event, Level.ERROR);

            decrementFilterCount(request);
            throw e;
         }

         if (!event.getFlow().is(BaseRewrite.ServletRewriteFlow.ABORT_REQUEST))
         {
            if (log.isDebugEnabled())
               log.debug("RewriteFilter passing control of request to underlying application.");

            if (response.isCommitted() && log.isWarnEnabled())
               log.warn("Response has already been committed, and further write operations are not permitted. "
                        + "This may result in an IllegalStateException being triggered by the underlying application. To avoid this situation, "
                        + "consider adding a Rule `.when(Direction.isInbound().and(Response.isCommitted())).perform(Lifecycle.abort())`, or "
                        + "figure out where the response is being incorrectly committed and correct the bug in the offending code.");

            chain.doFilter(event.getRequest(), event.getResponse());

            if (log.isDebugEnabled())
               log.debug("Control of request returned to RewriteFilter.");
         }

         for (RewriteLifecycleListener<Rewrite> listener : listeners)
         {
            if (listener.handles(event))
               listener.afterInboundLifecycle(event);
         }

         if (getFilterCount(request) == 1)
            AbstractRewrite.logEvaluatedRules(event, Level.DEBUG);

         decrementFilterCount(request);
      }
   }

   public InboundServletRewrite<ServletRequest, ServletResponse> createRewriteEvent(final ServletRequest request,
            final ServletResponse response)
   {
      for (InboundRewriteProducer<ServletRequest, ServletResponse> producer : inbound)
      {
         InboundServletRewrite<ServletRequest, ServletResponse> event = producer
                  .createInboundRewrite(request, response, servletContext);
         if (event != null)
            return event;
      }
      return null;
   }

   private void rewrite(final InboundServletRewrite<ServletRequest, ServletResponse> event)
            throws ServletException, IOException
   {
      int listenerCount = listeners.size();
      for (int i = 0; i < listenerCount; i++)
      {
         RewriteLifecycleListener<Rewrite> listener = listeners.get(i);
         if (listener.handles(event))
            listener.beforeInboundRewrite(event);
      }

      int providerCount = providers.size();
      for (int i = 0; i < providerCount; i++)
      {
         RewriteProvider<ServletContext, Rewrite> provider = providers.get(i);
         if (provider.handles(event))
         {
            provider.rewrite(event);

            if (event.getFlow().is(BaseRewrite.ServletRewriteFlow.HANDLED))
            {
               if (log.isDebugEnabled())
                  log.debug("Event flow marked as HANDLED. No further processing will occur.");
               break;
            }
         }
      }

      for (int i = 0; i < listenerCount; i++)
      {
         RewriteLifecycleListener<Rewrite> listener = listeners.get(i);
         if (listener.handles(event))
            listener.afterInboundRewrite(event);
      }

      int handlerCount = resultHandlers.size();
      for (int i = 0; i < handlerCount; i++)
      {
         if (resultHandlers.get(i).handles(event))
            resultHandlers.get(i).handleResult(event);
      }
   }

   @Override
   public void destroy()
   {
      log.info("RewriteFilter shutting down...");

      for (RewriteProvider<ServletContext, Rewrite> provider : providers) {
         if (provider instanceof ServletRewriteProvider)
            ((ServletRewriteProvider<?>) provider).shutdown(servletContext);
      }

      log.info("RewriteFilter deactivated.");
   }

   private int getFilterCount(ServletRequest request)
   {
      return (Integer) request.getAttribute(FILTER_COUNT_KEY);
   }

   private void decrementFilterCount(ServletRequest request)
   {
      Integer count = (Integer) request.getAttribute(FILTER_COUNT_KEY);
      if (count != null)
      {
         count--;
      }
      request.setAttribute(FILTER_COUNT_KEY, count);
   }

   private void incrementFilterCount(ServletRequest request)
   {
      Integer count = (Integer) request.getAttribute(FILTER_COUNT_KEY);

      if (count == null)
         count = 1;
      else
         count++;

      request.setAttribute(FILTER_COUNT_KEY, count);
   }

}
TOP

Related Classes of org.ocpsoft.rewrite.servlet.RewriteFilter

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.