Package com.gitblit.servlet

Source Code of com.gitblit.servlet.PagesServlet

/*
* Copyright 2012 gitblit.com.
*
* 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 com.gitblit.servlet;

import java.io.IOException;
import java.text.MessageFormat;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

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

import org.eclipse.jgit.lib.FileMode;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevTree;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.gitblit.Constants;
import com.gitblit.IStoredSettings;
import com.gitblit.Keys;
import com.gitblit.dagger.DaggerServlet;
import com.gitblit.manager.IRepositoryManager;
import com.gitblit.models.PathModel;
import com.gitblit.models.RefModel;
import com.gitblit.utils.ArrayUtils;
import com.gitblit.utils.ByteFormat;
import com.gitblit.utils.JGitUtils;
import com.gitblit.utils.MarkdownUtils;
import com.gitblit.utils.StringUtils;
import com.gitblit.wicket.MarkupProcessor;
import com.gitblit.wicket.MarkupProcessor.MarkupDocument;

import dagger.ObjectGraph;

/**
* Serves the content of a gh-pages branch.
*
* @author James Moger
*
*/
public class PagesServlet extends DaggerServlet {

  private static final long serialVersionUID = 1L;

  private transient Logger logger = LoggerFactory.getLogger(PagesServlet.class);

  private IStoredSettings settings;

  private IRepositoryManager repositoryManager;

  @Override
  protected void inject(ObjectGraph dagger) {
    this.settings = dagger.get(IStoredSettings.class);
    this.repositoryManager = dagger.get(IRepositoryManager.class);
  }

  /**
   * Returns an url to this servlet for the specified parameters.
   *
   * @param baseURL
   * @param repository
   * @param path
   * @return an url
   */
  public static String asLink(String baseURL, String repository, String path) {
    if (baseURL.length() > 0 && baseURL.charAt(baseURL.length() - 1) == '/') {
      baseURL = baseURL.substring(0, baseURL.length() - 1);
    }
    return baseURL + Constants.PAGES + repository + "/" + (path == null ? "" : ("/" + path));
  }

  /**
   * Retrieves the specified resource from the gh-pages branch of the
   * repository.
   *
   * @param request
   * @param response
   * @throws javax.servlet.ServletException
   * @throws java.io.IOException
   */
  private void processRequest(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {
    String path = request.getPathInfo();
    if (path.toLowerCase().endsWith(".git")) {
      // forward to url with trailing /
      // this is important for relative pages links
      response.sendRedirect(request.getServletPath() + path + "/");
      return;
    }
    if (path.charAt(0) == '/') {
      // strip leading /
      path = path.substring(1);
    }

    // determine repository and resource from url
    String repository = "";
    String resource = "";
    Repository r = null;
    int offset = 0;
    while (r == null) {
      int slash = path.indexOf('/', offset);
      if (slash == -1) {
        repository = path;
      } else {
        repository = path.substring(0, slash);
      }
      r = repositoryManager.getRepository(repository, false);
      offset = slash + 1;
      if (offset > 0) {
        resource = path.substring(offset);
      }
      if (repository.equals(path)) {
        // either only repository in url or no repository found
        break;
      }
    }

    ServletContext context = request.getSession().getServletContext();

    try {
      if (r == null) {
        // repository not found!
        String mkd = MessageFormat.format(
            "# Error\nSorry, no valid **repository** specified in this url: {0}!",
            repository);
        error(response, mkd);
        return;
      }

      // retrieve the content from the repository
      RefModel pages = JGitUtils.getPagesBranch(r);
      RevCommit commit = JGitUtils.getCommit(r, pages.getObjectId().getName());

      if (commit == null) {
        // branch not found!
        String mkd = MessageFormat.format(
            "# Error\nSorry, the repository {0} does not have a **gh-pages** branch!",
            repository);
        error(response, mkd);
        return;
      }

      MarkupProcessor processor = new MarkupProcessor(settings);
      String [] encodings = settings.getStrings(Keys.web.blobEncodings).toArray(new String[0]);

      RevTree tree = commit.getTree();

      String res = resource;
      if (res.endsWith("/")) {
        res = res.substring(0, res.length() - 1);
      }

      List<PathModel> pathEntries = JGitUtils.getFilesInPath(r, res, commit);

      byte[] content = null;
      if (pathEntries.isEmpty()) {
        // not a path, a specific resource
        try {
          String contentType = context.getMimeType(res);
          if (contentType == null) {
            contentType = "text/plain";
          }
          if (contentType.startsWith("text")) {
            content = JGitUtils.getStringContent(r, tree, res, encodings).getBytes(
                Constants.ENCODING);
          } else {
            content = JGitUtils.getByteContent(r, tree, res, false);
          }
          response.setContentType(contentType);
        } catch (Exception e) {
        }
      } else {
        // path request
        if (!request.getPathInfo().endsWith("/")) {
          // redirect to trailing '/' url
          response.sendRedirect(request.getServletPath() + request.getPathInfo() + "/");
          return;
        }

        Map<String, String> names = new TreeMap<String, String>();
        for (PathModel entry : pathEntries) {
          names.put(entry.name.toLowerCase(), entry.name);
        }

        List<String> extensions = new ArrayList<String>();
        extensions.add("html");
        extensions.add("htm");
        extensions.addAll(processor.getMarkupExtensions());
        for (String ext : extensions) {
          String key = "index." + ext;

          if (names.containsKey(key)) {
            String fileName = names.get(key);
            String fullPath = fileName;
            if (!res.isEmpty()) {
              fullPath = res + "/" + fileName;
            }
            String stringContent = JGitUtils.getStringContent(r, tree, fullPath, encodings);
            if (stringContent == null) {
              continue;
            }
            content = stringContent.getBytes(Constants.ENCODING);
            if (content != null) {
              res = fullPath;
              // assume text/html unless the servlet container
              // overrides
              response.setContentType("text/html; charset=" + Constants.ENCODING);
              break;
            }
          }
        }
      }

      // no content, document list or custom 404 page
      if (ArrayUtils.isEmpty(content)) {
        if (pathEntries.isEmpty()) {
          // 404
          String custom404 = JGitUtils.getStringContent(r, tree, "404.html", encodings);
          if (!StringUtils.isEmpty(custom404)) {
            content = custom404.getBytes(Constants.ENCODING);
          }

          // still no content
          if (ArrayUtils.isEmpty(content)) {
            String str = MessageFormat.format(
                "# Error\nSorry, the requested resource **{0}** was not found.",
                resource);
            content = MarkdownUtils.transformMarkdown(str).getBytes(Constants.ENCODING);
          }

          try {
            // output the content
            logger.warn("Pages 404: " + resource);
            response.setStatus(HttpServletResponse.SC_NOT_FOUND);
            response.getOutputStream().write(content);
            response.flushBuffer();
          } catch (Throwable t) {
            logger.error("Failed to write page to client", t);
          }
        } else {
          // document list
          response.setContentType("text/html");
          response.getWriter().append("<style>table th, table td { min-width: 150px; text-align: left; }</style>");
          response.getWriter().append("<table>");
          response.getWriter().append("<thead><tr><th>path</th><th>mode</th><th>size</th></tr>");
          response.getWriter().append("</thead>");
          response.getWriter().append("<tbody>");
          String pattern = "<tr><td><a href=\"{0}/{1}\">{1}</a></td><td>{2}</td><td>{3}</td></tr>";
          final ByteFormat byteFormat = new ByteFormat();
          if (!pathEntries.isEmpty()) {
            if (pathEntries.get(0).path.indexOf('/') > -1) {
              // we are in a subdirectory, add parent directory link
              pathEntries.add(0, new PathModel("..", resource + "/..", 0, FileMode.TREE.getBits(), null, null));
            }
          }

          String basePath = request.getServletPath() + request.getPathInfo();
          if (basePath.charAt(basePath.length() - 1) == '/') {
            // strip trailing slash
            basePath = basePath.substring(0, basePath.length() - 1);
          }
          for (PathModel entry : pathEntries) {
            response.getWriter().append(MessageFormat.format(pattern, basePath, entry.name,
                JGitUtils.getPermissionsFromMode(entry.mode), byteFormat.format(entry.size)));
          }
          response.getWriter().append("</tbody>");
          response.getWriter().append("</table>");
        }
        return;
      }

      // check to see if we should transform markup files
      String ext = StringUtils.getFileExtension(resource);
      if (processor.getMarkupExtensions().contains(ext)) {
        String markup = new String(content, Constants.ENCODING);
        MarkupDocument markupDoc = processor.parse(repository, commit.getName(), resource, markup);
        content = markupDoc.html.getBytes("UTF-8");
        response.setContentType("text/html; charset=" + Constants.ENCODING);
      }

      try {
        // output the content
        response.setHeader("Cache-Control", "public, max-age=3600, must-revalidate");
        response.setDateHeader("Last-Modified", JGitUtils.getCommitDate(commit).getTime());
        response.getOutputStream().write(content);
        response.flushBuffer();
      } catch (Throwable t) {
        logger.error("Failed to write page to client", t);
      }

    } catch (Throwable t) {
      logger.error("Failed to write page to client", t);
    } finally {
      r.close();
    }
  }

  private void error(HttpServletResponse response, String mkd) throws ServletException,
      IOException, ParseException {
    String content = MarkdownUtils.transformMarkdown(mkd);
    response.setContentType("text/html; charset=" + Constants.ENCODING);
    response.getWriter().write(content);
  }

  @Override
  protected void doPost(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {
    processRequest(request, response);
  }

  @Override
  protected void doGet(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {
    processRequest(request, response);
  }
}
TOP

Related Classes of com.gitblit.servlet.PagesServlet

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.