org.olat.commons.servlets.StaticsLegacyDispatcher.java Source code

Java tutorial

Introduction

Here is the source code for org.olat.commons.servlets.StaticsLegacyDispatcher.java

Source

/**
* OLAT - Online Learning and Training<br>
* http://www.olat.org
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); <br>
* you may not use this file except in compliance with the License.<br>
* You may obtain a copy of the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing,<br>
* software distributed under the License is distributed on an "AS IS" BASIS, <br>
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
* See the License for the specific language governing permissions and <br>
* limitations under the License.
* <p>
* Copyright (c) since 2004 at Multimedia- & E-Learning Services (MELS),<br>
* University of Zurich, Switzerland.
* <hr>
* <a href="http://www.openolat.org">
* OpenOLAT - Online Learning and Training</a><br>
* This file has been modified by the OpenOLAT community. Changes are licensed
* under the Apache 2.0 license as the original file.
*/
package org.olat.commons.servlets;

import java.io.IOException;
import java.io.InputStream;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.io.IOUtils;
import org.olat.commons.servlets.pathhandlers.PathHandler;
import org.olat.commons.servlets.util.ResourceDescriptor;
import org.olat.core.dispatcher.Dispatcher;
import org.olat.core.dispatcher.DispatcherModule;
import org.olat.core.gui.media.MediaResource;
import org.olat.core.gui.media.ServletUtil;
import org.olat.core.logging.OLog;
import org.olat.core.logging.Tracing;

/**
 * @author Mike Stock Comment:
 *         <p>
 *         This class use to be the StaticsServlet.class. It has been refactored
 *         to implement the dispatcher interface. Please note that this statics
 *         dispatcher is legacy and should not be used to deliver static
 *         resources anymore. See the deprecated comments for more information.
 *         <p>
 *         This servlet extracts a handlerName from the first sub-path of the
 *         request's relative path. StaticsModule provides a handler class based
 *         on that name. Handler classes are configured in jpublish-xml's config
 *         for the StaticsModule. Handlers must implement the PathHandler
 *         interface. See FilePathHandler for an example of a PathHandler which
 *         resolves files in a filesystem. A handler is called by this servlet
 *         with the remaining path as argument. The handlers know how to get to
 *         the resource themselves.
 *         <p>
 * @deprecated Please use GlobalMapperRegistry if you need to provide an url for
 *             e.g. static resources which are shared by all users
 */
public class StaticsLegacyDispatcher implements Dispatcher {
    private static final OLog log = Tracing.createLoggerFor(StaticsLegacyDispatcher.class);

    /**
     * Default constructor.
     */
    public StaticsLegacyDispatcher() {
        super();
    }

    /**
      * @see org.olat.core.dispatcher.Dispatcher#execute(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, java.lang.String)
      */
    @Override
    public void execute(HttpServletRequest req, HttpServletResponse resp) {
        try {
            String method = req.getMethod();
            if (method.equals("GET")) {
                doGet(req, resp);
            } else if (method.equals("HEAD")) {
                doHead(req, resp);
            } else {
                DispatcherModule.sendNotFound(req.getRequestURI(), resp);
            }
        } catch (IOException e) {
            /*
             * silently ignore forward errors (except in debug mode), since IE
             * causes tons of such messages by its double GET request
             */
            if (log.isDebug()) {
                log.debug("could not execute legacy statics method:" + e.toString() + ",msg:" + e.getMessage());
            }
        }
    }

    /**
     * Process a GET request for the specified resource.
     * 
     * @param request
     *            The servlet request we are processing
     * @param response
     *            The servlet response we are creating
     * 
     * @exception IOException
     *                if an input/output error occurs
     */
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
        // just to indicate that method must return if false is returned
        if (!serveResource(request, response, true)) {
            return;
        }
    }

    /**
     * Process a HEAD request for the specified resource.
     * 
     * @param request
     *            The servlet request we are processing
     * @param response
     *            The servlet response we are creating
     * 
     * @exception IOException
     *                if an input/output error occurs
     */
    protected void doHead(HttpServletRequest request, HttpServletResponse response) throws IOException {
        // just to indicate that method must return if false is returned
        if (!serveResource(request, response, false)) {
            return;
        }
    }

    /**
     * Serve the requested resource.
     * 
     * @param request
     * @param response
     * @param copyContent
     * @return False if serving the resource failed/was aborted.
     * @throws IOException
     */
    private boolean serveResource(HttpServletRequest request, HttpServletResponse response, boolean copyContent)
            throws IOException {
        // just another internal forward or even a direct call
        String path = getRelativePath(request);
        if (path.indexOf("/secstatic/") == 0) {
            path = path.substring(10, path.length());
        }
        PathHandler handler = null;
        String relPath = null;
        String handlerName = null;
        long start = 0;

        boolean logDebug = log.isDebug();
        if (logDebug)
            start = System.currentTimeMillis();
        try {
            relPath = path.substring(1);
            int index = relPath.indexOf('/');
            if (index != -1) {
                handlerName = relPath.substring(0, index);
                relPath = relPath.substring(index);
            }

            if (handlerName != null) {
                handler = StaticsModule.getInstance(handlerName);
            }
        } catch (IndexOutOfBoundsException e) {
            // if some problem with the url, we assign no handler
        }

        if (handler == null || relPath == null) {
            // no handler found or relPath incomplete
            response.sendError(HttpServletResponse.SC_NOT_FOUND, request.getRequestURI());
            return false;
        }

        ResourceDescriptor rd = handler.getResourceDescriptor(request, relPath);
        if (rd == null) {
            // no handler found or relPath incomplete
            response.sendError(HttpServletResponse.SC_NOT_FOUND, request.getRequestURI());
            return false;
        }

        // check if modified since
        long ifModifiedSince = request.getDateHeader("If-Modified-Since");
        long lastMod = rd.getLastModified();
        if (lastMod != -1L && ifModifiedSince >= lastMod) {
            response.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
            return false;
        }

        // server the resource
        if (copyContent) {
            InputStream is = handler.getInputStream(request, rd);
            if (is == null) {
                // resource not found or access denied
                response.sendError(HttpServletResponse.SC_NOT_FOUND, request.getRequestURI());
                return false;
            }
            StaticMediaResource smr = new StaticMediaResource(is, rd);
            ServletUtil.serveResource(request, response, smr);
            if (logDebug) {
                long stop = System.currentTimeMillis();
                log.debug("Serving resource '" + relPath + "' (" + rd.getSize() + " bytes) in " + (stop - start)
                        + "ms with handler '" + handlerName + "'.");
            }
        }
        return true;
    }

    /**
     * Return the relative path associated with this servlet.
     * 
     * @param request
     *            The servlet request we are processing
     */
    private String getRelativePath(HttpServletRequest request) {

        String result = request.getPathInfo();
        if ((result == null) || (result.equals(""))) {
            result = "/";
        }
        return ServletUtil.normalizePath(result);
    }

    private static class StaticMediaResource implements MediaResource {

        private final InputStream inStream;
        private final ResourceDescriptor rd;

        public StaticMediaResource(InputStream inStream, ResourceDescriptor rd) {
            this.inStream = inStream;
            this.rd = rd;
        }

        @Override
        public boolean acceptRanges() {
            return false;
        }

        @Override
        public String getContentType() {
            return rd.getContentType();
        }

        @Override
        public Long getSize() {
            return rd.getSize();
        }

        @Override
        public InputStream getInputStream() {
            return inStream;
        }

        @Override
        public Long getLastModified() {
            return rd.getLastModified();
        }

        @Override
        public void prepare(HttpServletResponse hres) {
            //
        }

        @Override
        public void release() {
            IOUtils.closeQuietly(inStream);
        }
    }
}