org.jlibrary.web.servlet.JLibraryContentLoaderServlet.java Source code

Java tutorial

Introduction

Here is the source code for org.jlibrary.web.servlet.JLibraryContentLoaderServlet.java

Source

/*
* jLibrary, Open Source Document Management System
* 
* Copyright (c) 2003-2006, Martn Prez Marin, Blandware (represented by
* Andrey Grebnev), and individual contributors as indicated by the
* @authors tag. See copyright.txt in the distribution for a full listing of
* individual contributors. All rights reserved.
* 
* This is free software; you can redistribute it and/or modify it
* under the terms of the Modified BSD License as published by the Free 
* Software Foundation.
* 
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the Modified
* BSD License for more details.
* 
* You should have received a copy of the Modified BSD License along with 
* this software; if not, write to the Free Software Foundation, Inc., 
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA, or see the
* FSF site: http://www.fsf.org.
*/
package org.jlibrary.web.servlet;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.commons.lang.StringUtils;
import org.apache.jackrabbit.util.Text;
import org.apache.log4j.Logger;
import org.jlibrary.core.entities.Category;
import org.jlibrary.core.entities.Directory;
import org.jlibrary.core.entities.Document;
import org.jlibrary.core.entities.Node;
import org.jlibrary.core.entities.Repository;
import org.jlibrary.core.entities.RepositoryInfo;
import org.jlibrary.core.entities.ServerProfile;
import org.jlibrary.core.entities.Ticket;
import org.jlibrary.core.entities.Types;
import org.jlibrary.core.factory.JLibraryServiceFactory;
import org.jlibrary.core.jcr.JCRRepositoryService;
import org.jlibrary.core.profiles.LocalServerProfile;
import org.jlibrary.core.repository.RepositoryService;
import org.jlibrary.core.repository.exception.NodeNotFoundException;
import org.jlibrary.core.repository.exception.RepositoryException;
import org.jlibrary.core.repository.exception.RepositoryNotFoundException;
import org.jlibrary.core.security.SecurityException;
import org.jlibrary.core.util.FileUtils;
import org.jlibrary.web.RepositoryRegistry;
import org.jlibrary.web.WebConstants;
import org.jlibrary.web.freemarker.FreemarkerExporter;
import org.jlibrary.web.freemarker.RepositoryContext;
import org.jlibrary.web.services.ConfigurationService;
import org.jlibrary.web.services.StatsService;
import org.jlibrary.web.services.TicketService;
import org.springframework.context.ApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;

/**
 * This servlet listens for content requests following a model very similar to REST. 
 * Requests will have the format /webapp/repositories/URL and jLibrary will try to load 
 * the content matching the given URL path.
 * 
 * @author mpermar
 */
@SuppressWarnings("serial")
public class JLibraryContentLoaderServlet extends JLibraryServlet {

    private static Logger logger = Logger.getLogger(JLibraryContentLoaderServlet.class);

    private ServerProfile profile = new LocalServerProfile();
    private StatsService statsService = StatsService.newInstance();

    private RepositoryService repositoryService;

    @Override
    public void init() throws ServletException {

        super.init();

        try {
            ApplicationContext context = WebApplicationContextUtils
                    .getRequiredWebApplicationContext(getServletContext());
            ConfigurationService configService = (ConfigurationService) context.getBean("template");
            TicketService.getTicketService().init(configService);

            repositoryService = JLibraryServiceFactory.getInstance(profile).getRepositoryService();
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        processContent(req, resp);
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        processContent(req, resp);
    }

    /*
    @Override
    protected long getLastModified(HttpServletRequest req) {
        
       String appURL = req.getContextPath();
       String uri = req.getRequestURI();
       String path = StringUtils.difference(appURL+"/repositories",uri);
       if (path.equals("") || path.equals("/")) {
     // call to /repositories
     return super.getLastModified(req);
       }
           
       String[] pathElements = StringUtils.split(path,"/");
           
       if ((pathElements.length > 1) && (pathElements[1].equals("categories"))) {
     //TODO: Cache categories
     return super.getLastModified(req);   
       }
           
       try {
     String repositoryName = getRepositoryName(req);
     HttpSession session = req.getSession(false);
     if ((repositoryName == null) || (session == null)) {
        return super.getLastModified(req);
     }
     Ticket ticket = (Ticket)session.getAttribute(
           (TicketService.SESSION_TICKET_ID+repositoryName).toLowerCase());
        
     if (ticket == null) {
        return super.getLastModified(req);
     }
         
     Node node = null;
     Repository repository = loadRepository(repositoryName,ticket);
     String nodePath = StringUtils.difference(appURL+"/repositories/"+repositoryName,uri);
     if (pathElements.length == 1) {
        // TODO: cache repository root
        node = repository.getRoot();
     } else {                     
        node = findNode(ticket, repositoryService, nodePath);
     }
     if (node.isResource()) {
        // We will cache all resources
        return node.getDate().getTime();
     } else if (node.isDocument()) {
            
        if (ticket.getUser().getName().equals(WebConstants.ANONYMOUS_WEB_USERNAME) ||
           "true".equals(req.getParameter("download"))) {
           // We will cache downloads or guest pages
           return node.getDate().getTime();
        }
     }
       } catch (Exception e) {
     logger.error(e.getMessage(),e);
     return super.getLastModified(req);
       }
       return super.getLastModified(req);
    }
    */
    private void processContent(HttpServletRequest req, HttpServletResponse resp) {
        try {
            resp.setCharacterEncoding("ISO-8859-1");
            req.setCharacterEncoding("ISO-8859-1");
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }
        String appURL = req.getContextPath();
        String uri = req.getRequestURI();
        String path = StringUtils.difference(appURL + "/repositories", uri);
        if (path.equals("") || path.equals("/")) {
            // call to /repositories 
            try {
                Ticket ticket = TicketService.getTicketService().getSystemTicket();
                List repoInfo = repositoryService.findAllRepositoriesInfo(ticket);
                Iterator it = repoInfo.iterator();
                List<RepositoryInfo> repositories = new ArrayList<RepositoryInfo>();
                while (it.hasNext()) {
                    RepositoryInfo info = (RepositoryInfo) it.next();
                    if (info.getName().equals("system") || info.getName().equals("default")) {
                        continue;
                    }
                    repositories.add(info);

                }
                RequestDispatcher rd = getServletContext().getRequestDispatcher("/repositories.jsp");
                req.setAttribute("repositories", repositories);
                rd.forward(req, resp);

                return;
            } catch (Exception e) {
                logger.error(e.getMessage(), e);
                //TODO: mandar a una pgina de error esttica
            }
        }
        String[] pathElements = StringUtils.split(path, "/");

        String repositoryName = getRepositoryName(req);
        Ticket ticket = TicketService.getTicketService().getTicket(req, repositoryName);
        Repository repository = null;
        try {
            repository = loadRepository(repositoryName, ticket);

            if (pathElements.length > 1) {
                if (pathElements[1].equals("categories")) {
                    String categoryPath = StringUtils
                            .difference(appURL + "/repositories/" + repositoryName + "/categories", uri);
                    Category category = findCategory(repository, pathElements);
                    if (category == null) {
                        resp.setStatus(HttpServletResponse.SC_NOT_FOUND);
                        resp.flushBuffer();
                    } else {
                        String output = exportCategory(req, resp, ticket, repository, category);
                        resp.getOutputStream().write(output.getBytes());
                        resp.flushBuffer();
                    }
                    return;
                }
            }

            Node node = null;
            String nodePath = StringUtils.difference(appURL + "/repositories/" + repositoryName, uri);
            if (pathElements.length == 1) {
                node = repository.getRoot();
            } else {
                node = findNode(ticket, repositoryService, nodePath);
            }
            if (node == null) {
                logger.debug("Node could not be found");
            } else {
                req.setAttribute("node", node);
                /*
                resp.setDateHeader("Last-Modified", node.getDate().getTime());
                resp.setDateHeader("Age", 86400); // cache a day
                */
                if (node.isDocument()) {
                    Document document = (Document) node;
                    byte[] output;
                    if ("true".equals(req.getParameter("download"))) {
                        output = repositoryService.loadDocumentContent(document.getId(), ticket);
                        if (document.isImage()) {
                            resp.setContentType(
                                    Types.getMimeTypeForExtension(FileUtils.getExtension(document.getPath())));
                        } else {
                            resp.setContentType("application/octet-stream");
                        }
                    } else {
                        output = exportDocument(req, ticket, repository, node).getBytes();
                    }
                    resp.getOutputStream().write(output);
                    resp.flushBuffer();
                } else if (node.isDirectory()) {
                    // Search for a root document (index.html)
                    String output = exportDirectory(req, resp, ticket, repository, node);
                    resp.getOutputStream().write(output.getBytes());
                    resp.flushBuffer();
                } else if (node.isResource()) {
                    exportResouce(req, resp, repositoryService, ticket, node);

                }
            }
        } catch (NodeNotFoundException nnfe) {
            logErrorAndForward(req, resp, repositoryName, nnfe, "The requested page could not be found.");
        } catch (SecurityException se) {
            logErrorAndForward(req, resp, repositoryName, se,
                    "You do not have enough rights for accessing to the requested page.");
        } catch (Exception e) {
            //TODO:mandar a pgina de error esttica
            e.printStackTrace();
        }
    }

    private Repository loadRepository(String repositoryName, Ticket userTicket)
            throws RepositoryNotFoundException, RepositoryException, SecurityException {

        Repository repository;
        RepositoryRegistry registry = RepositoryRegistry.getInstance();
        repository = registry.getRepository(repositoryName);
        if (repository == null) {
            //TODO: Probably this could be improved. We can use guest tickets 
            // for holding all the information we need (categories and some 
            // user ids). However, note that holding a repository loaded with 
            // a constrained permission set (guest) could be insufficient for 
            // other scenarios.
            repository = repositoryService.findRepository(repositoryName, userTicket);
            repository.setServerProfile(profile);
            RepositoryRegistry.getInstance().addRepository(repository, repositoryName);
        }
        // Change user ticket. This is to use security constraints when applying templates
        repository.setTicket(userTicket);
        return repository;
    }

    private Node findNode(Ticket ticket, RepositoryService repositoryService, String nodePath)
            throws RepositoryException, SecurityException, NodeNotFoundException {

        Node node;
        try {
            node = ((JCRRepositoryService) repositoryService).findNodeByPath(ticket, nodePath);
        } catch (NodeNotFoundException nnfe) {
            // Perhaps somebody has unescaped the name
            String unescapedPath = Text.unescape(nodePath);
            node = ((JCRRepositoryService) repositoryService).findNodeByPath(ticket, unescapedPath);
        }
        return node;
    }

    private Category findCategory(Repository repository, String[] pathElements) {

        int i = 2;
        Category category = null;
        Set categoriesSet = null;
        while (i < pathElements.length) {
            String categoryName = Text.unescape(pathElements[i]);

            if (category == null) {
                categoriesSet = repository.getCategories();
            } else {
                categoriesSet = category.getCategories();
            }
            Iterator it = categoriesSet.iterator();
            while (it.hasNext()) {
                Category child = (Category) it.next();
                //String childEscapedName = Text.escape(child.getName());
                if (child.getName().equals(categoryName)) {
                    category = child;
                    break;
                }
            }
            i++;
        }
        return category;
    }

    private String exportDocument(HttpServletRequest request, Ticket ticket, Repository repository, Node node) {

        try {
            RepositoryContext context = new RepositoryContext(repository, getServletContext(), getContext());
            context.setTicket(ticket);
            FreemarkerExporter exporter = new FreemarkerExporter();
            exporter.setRootURL(getRootURL(request));
            exporter.setRepositoryURL(getRepositoryURL(request, repository.getName()));
            exporter.setError((String) request.getAttribute("error"));
            exporter.initExportProcess(context);
            statsService.incServedDocuments();
            return exporter.exportDocument((Document) node, context, "document.ftl");
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            return "";
        }
    }

    private String exportDirectory(HttpServletRequest request, HttpServletResponse response, Ticket ticket,
            Repository repository, Node node) {

        try {
            RepositoryContext context = new RepositoryContext(repository, getServletContext(), getContext());
            context.setTicket(ticket);
            FreemarkerExporter exporter = new FreemarkerExporter();
            exporter.setRootURL(getRootURL(request));
            exporter.setRepositoryURL(getRepositoryURL(request, repository.getName()));
            exporter.setError((String) request.getAttribute("error"));
            exporter.initExportProcess(context);
            statsService.incServedDirectories();
            if ((request.getParameter("rss") != null) && (request.getParameter("rss").equals("true"))) {
                response.setContentType("application/rss+xml");
                return exporter.exportDirectory((Directory) node, context, "directory-rss.ftl");
            } else {
                return exporter.exportDirectory((Directory) node, context, "directory.ftl");
            }

        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            return "";
        }
    }

    private String exportCategory(HttpServletRequest request, HttpServletResponse response, Ticket ticket,
            Repository repository, Category category) {

        try {

            RepositoryContext context = new RepositoryContext(repository, getServletContext(), getContext());
            context.setTicket(ticket);
            FreemarkerExporter exporter = new FreemarkerExporter();
            exporter.setRootURL(getRootURL(request));
            exporter.setRepositoryURL(getRepositoryURL(request, repository.getName()));
            exporter.setError((String) request.getAttribute("error"));
            exporter.initExportProcess(context);
            statsService.incServedCategories();
            if ((request.getParameter("rss") != null) && (request.getParameter("rss").equals("true"))) {
                response.setContentType("application/rss+xml");
                return exporter.exportCategory(category, context, "category-rss.ftl");
            } else {
                return exporter.exportCategory(category, context, "category.ftl");
            }
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            return "";
        }
    }

    private void exportResouce(HttpServletRequest req, HttpServletResponse resp,
            RepositoryService repositoryService, Ticket ticket, Node node) {

        try {
            String extension = FileUtils.getExtension(node.getPath());
            String mime = Types.getMimeTypeForExtension(extension);
            resp.setContentType(mime);
            repositoryService.loadResourceNodeContent(ticket, node.getId(), resp.getOutputStream());
            resp.getOutputStream().flush();
            statsService.incAttachments();
        } catch (Exception e) {
            resp.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
            logger.error(e.getMessage(), e);
            return;
        }
    }
}