org.esigate.servlet.ServletExtension.java Source code

Java tutorial

Introduction

Here is the source code for org.esigate.servlet.ServletExtension.java

Source

/* 
 * 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.esigate.servlet;

import java.io.IOException;
import java.util.Properties;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;

import org.apache.http.HttpStatus;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.esigate.ConfigurationException;
import org.esigate.Driver;
import org.esigate.HttpErrorPage;
import org.esigate.Parameters;
import org.esigate.api.ContainerRequestContext;
import org.esigate.events.Event;
import org.esigate.events.EventDefinition;
import org.esigate.events.EventManager;
import org.esigate.events.IEventListener;
import org.esigate.events.impl.FetchEvent;
import org.esigate.extension.Extension;
import org.esigate.http.IncomingRequest;
import org.esigate.http.OutgoingRequest;
import org.esigate.http.OutgoingRequestContext;
import org.esigate.servlet.impl.ResponseCapturingWrapper;
import org.esigate.servlet.impl.ResponseSender;
import org.esigate.util.UriUtils;

/**
 * Extension to enable local or cross-context includes inside a J2EE web application.
 * 
 * This extension does not support background revalidation as it is not compliant with the Servlet request lifecycle.
 * 
 * @author Francois-Xavier Bonnet
 * 
 */
public class ServletExtension implements Extension, IEventListener {
    private Driver driver;
    private String context;
    private int maxObjectSize;
    private final ResponseSender responseSender = new ResponseSender();

    @Override
    public void init(Driver driverParam, Properties properties) {
        this.driver = driverParam;
        driverParam.getEventManager().register(EventManager.EVENT_FETCH_PRE, this);
        context = properties.getProperty("context");
        maxObjectSize = Parameters.MAX_OBJECT_SIZE.getValue(properties);
        if (!Parameters.STALE_WHILE_REVALIDATE.getDefaultValue()
                .equals(Parameters.STALE_WHILE_REVALIDATE.getValue(properties))) {
            throw new ConfigurationException("ServletExtension does not support background revalidation ("
                    + driver.getConfiguration().getInstanceName() + ".staleWhileRevalidate="
                    + Parameters.STALE_WHILE_REVALIDATE.getValue(properties) + ")");
        }
    }

    @Override
    public boolean event(EventDefinition id, Event event) {
        FetchEvent fetchEvent = (FetchEvent) event;
        if (EventManager.EVENT_FETCH_PRE.equals(id)) {
            String uriString = fetchEvent.getHttpRequest().getRequestLine().getUri();
            OutgoingRequest outgoingRequest = OutgoingRequestContext.adapt(fetchEvent.getHttpContext())
                    .getOutgoingRequest();
            IncomingRequest incomingRequest = outgoingRequest.getOriginalRequest().getOriginalRequest();
            String baseUrl = outgoingRequest.getBaseUrl().toString();
            if (outgoingRequest.getOriginalRequest().isExternal()) {
                // Non local absolute uri
                return true;
            } else {
                String relUrl = uriString;
                if (UriUtils.isAbsolute(relUrl)) {
                    relUrl = relUrl.substring(UriUtils.extractHost(relUrl).toURI().length());
                }
                relUrl = relUrl.substring(UriUtils.getPath(baseUrl).length());
                if (!relUrl.startsWith("/")) {
                    relUrl = "/" + relUrl;
                }
                ContainerRequestContext requestContext = outgoingRequest.getContainerRequestContext();
                CloseableHttpResponse result;
                if (!(requestContext instanceof HttpServletRequestContext)) {
                    String message = ServletExtension.class.getName()
                            + " can be used only inside a java servlet engine";
                    result = HttpErrorPage.generateHttpResponse(HttpStatus.SC_BAD_GATEWAY, message);
                } else {
                    HttpServletRequestContext httpServletRequestContext = (HttpServletRequestContext) requestContext;
                    try {
                        if (fetchEvent.getHttpContext().isProxy()) {
                            ResponseCapturingWrapper wrappedResponse = new ResponseCapturingWrapper(
                                    httpServletRequestContext.getResponse(), driver.getContentTypeHelper(), true,
                                    maxObjectSize, responseSender, incomingRequest);
                            if (context == null) {
                                httpServletRequestContext.getFilterChain()
                                        .doFilter(httpServletRequestContext.getRequest(), wrappedResponse);
                                result = wrappedResponse.getCloseableHttpResponse();
                            } else {
                                ServletContext crossContext = httpServletRequestContext.getServletContext()
                                        .getContext(context);
                                if (crossContext == null) {
                                    String message = "Context " + context
                                            + " does not exist or cross context disabled";
                                    result = HttpErrorPage.generateHttpResponse(HttpStatus.SC_BAD_GATEWAY, message);
                                } else {
                                    crossContext.getRequestDispatcher(relUrl)
                                            .forward(httpServletRequestContext.getRequest(), wrappedResponse);
                                    result = wrappedResponse.getCloseableHttpResponse();
                                }
                            }
                        } else {
                            ResponseCapturingWrapper wrappedResponse = new ResponseCapturingWrapper(
                                    httpServletRequestContext.getResponse(), driver.getContentTypeHelper(), false,
                                    maxObjectSize, responseSender, incomingRequest);
                            if (context == null) {
                                httpServletRequestContext.getRequest().getRequestDispatcher(relUrl)
                                        .forward(httpServletRequestContext.getRequest(), wrappedResponse);
                                result = wrappedResponse.getCloseableHttpResponse();
                            } else {
                                ServletContext crossContext = httpServletRequestContext.getServletContext()
                                        .getContext(context);
                                if (crossContext == null) {
                                    String message = "Context " + context
                                            + " does not exist or cross context disabled";
                                    result = HttpErrorPage.generateHttpResponse(HttpStatus.SC_BAD_GATEWAY, message);
                                } else {
                                    crossContext.getRequestDispatcher(relUrl)
                                            .include(httpServletRequestContext.getRequest(), wrappedResponse);
                                    result = wrappedResponse.getCloseableHttpResponse();
                                }
                            }
                        }
                    } catch (IOException | ServletException e) {
                        result = HttpErrorPage.generateHttpResponse(e);
                    }
                }
                fetchEvent.setHttpResponse(result);
                // Stop execution
                fetchEvent.setExit(true);
            }
        }
        return true;
    }
}