ServletExtension.java
- /*
- * 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;
- }
- }