org.jdesktop.wonderland.modules.contentrepo.web.servlet.BrowserServlet.java Source code

Java tutorial

Introduction

Here is the source code for org.jdesktop.wonderland.modules.contentrepo.web.servlet.BrowserServlet.java

Source

/**
 * Project Wonderland
 *
 * Copyright (c) 2004-2009, Sun Microsystems, Inc., All Rights Reserved
 *
 * Redistributions in source code form must reproduce the above
 * copyright and this condition.
 *
 * The contents of this file are subject to the GNU General Public
 * License, Version 2 (the "License"); you may not use this file
 * except in compliance with the License. A copy of the License is
 * available at http://www.opensource.org/licenses/gpl-license.php.
 *
 * Sun designates this particular file as subject to the "Classpath"
 * exception as provided by Sun in the License file that accompanied
 * this code.
 */

package org.jdesktop.wonderland.modules.contentrepo.web.servlet;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.fileupload.FileItemIterator;
import org.apache.commons.fileupload.FileItemStream;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.jdesktop.wonderland.front.admin.AdminRegistration;
import org.jdesktop.wonderland.modules.contentrepo.common.ContentCollection;
import org.jdesktop.wonderland.modules.contentrepo.common.ContentNode;
import org.jdesktop.wonderland.modules.contentrepo.common.ContentRepositoryException;
import org.jdesktop.wonderland.modules.contentrepo.common.ContentResource;
import org.jdesktop.wonderland.modules.contentrepo.web.spi.WebContentRepository;
import org.jdesktop.wonderland.modules.contentrepo.web.spi.WebContentRepositoryRegistry;
import org.jdesktop.wonderland.utils.RunUtil;

/**
 *
 * @author jkaplan
 */
public class BrowserServlet extends HttpServlet implements ServletContextListener {
    private static final Logger logger = Logger.getLogger(BrowserServlet.class.getName());

    private AdminRegistration ar;

    /** 
     * Processes requests for both HTTP <code>GET</code> and <code>POST</code> methods.
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        ServletContext sc = getServletContext();

        // get the repository
        WebContentRepositoryRegistry reg = WebContentRepositoryRegistry.getInstance();
        WebContentRepository wcr = reg.getRepository(sc);
        if (wcr == null) {
            error(request, response, "No content repositories found. <br>"
                    + "Please contact your system administrator for assistance.");
            return;
        }

        try {
            ContentNode node = translatePath(wcr, request.getPathInfo());
            if (node == null) {
                error(request, response, "Path " + request.getPathInfo() + " not found.");
                return;
            }

            String action = request.getParameter("action");
            if (action == null && ServletFileUpload.isMultipartContent(request)) {
                action = "upload";
            }

            if (action != null) {
                node = handleAction(request, response, node, action);
                if (node == null) {
                    // indicates that the action has handled forwarding on
                    // its own, for example to the error page
                    return;
                }
            }

            DirectoryEntry current = new DirectoryEntry(node);
            request.setAttribute("current", current);

            if (node instanceof ContentCollection) {
                handleCollection(request, response, (ContentCollection) node);
            } else if (node instanceof ContentResource) {
                handleResource(request, response, (ContentResource) node);
            } else {
                error(request, response, "Unknown node type " + node.getClass());
            }
        } catch (ContentRepositoryException cre) {
            throw new ServletException(cre);
        }
    }

    protected void error(HttpServletRequest request, HttpServletResponse response, String message)
            throws ServletException, IOException {
        request.setAttribute("message", message);
        RequestDispatcher rd = getServletContext().getRequestDispatcher("/error.jsp");
        rd.forward(request, response);
    }

    protected ContentNode translatePath(WebContentRepository wcr, String path) throws ContentRepositoryException {
        // find the root (system or users)
        ContentCollection root = null;

        if (path == null || path.equals("/")) {
            root = wcr.getRoot();
        } else if (path.startsWith("/system")) {
            path = path.substring("/system".length());
            root = wcr.getSystemRoot();
        } else if (path.startsWith("/users/")) {
            path = path.substring("/users/".length());
            String userId = path;

            int endIdx = path.indexOf("/");
            if (endIdx != -1) {
                userId = path.substring(0, endIdx);
                path = path.substring(endIdx);
            } else {
                path = null;
            }

            root = wcr.getUserRoot(userId);
        } else {
            root = wcr.getRoot();
        }

        if (root == null) {
            return null;
        }

        if (path == null || path.length() == 0 || path.equals("/")) {
            return root;
        }

        return root.getChild(path);
    }

    protected ContentNode handleAction(HttpServletRequest request, HttpServletResponse response, ContentNode node,
            String action) throws ServletException, IOException, ContentRepositoryException {
        if (action.equalsIgnoreCase("mkdir")) {
            return handleMkdir(request, response, node, action);
        } else if (action.equalsIgnoreCase("delete")) {
            return handleDelete(request, response, node, action);
        } else if (action.equalsIgnoreCase("upload")) {
            return handleUpload(request, response, node, action);
        } else {
            // do nothing
            return node;
        }
    }

    protected ContentNode handleMkdir(HttpServletRequest request, HttpServletResponse response, ContentNode node,
            String action) throws ServletException, IOException, ContentRepositoryException {
        String dirName = request.getParameter("dirname");
        if (dirName == null || dirName.trim().length() == 0) {
            error(request, response, "Invalid name");
            return null;
        }

        if (!(node instanceof ContentCollection)) {
            error(request, response, "Not a directory");
            return null;
        }

        ((ContentCollection) node).createChild(dirName, ContentNode.Type.COLLECTION);
        return node;
    }

    protected ContentNode handleDelete(HttpServletRequest request, HttpServletResponse response, ContentNode node,
            String action) throws ServletException, IOException, ContentRepositoryException {
        ContentCollection parent = node.getParent();
        if (parent == null) {
            error(request, response, "Cannot delete top-level node.");
            return null;
        }

        parent.removeChild(node.getName());
        return parent;
    }

    protected ContentNode handleUpload(HttpServletRequest request, HttpServletResponse response, ContentNode node,
            String action) throws ServletException, IOException, ContentRepositoryException {
        if (!(node instanceof ContentCollection)) {
            error(request, response, "Not a directory");
            return null;
        }

        ContentCollection dir = (ContentCollection) node;

        /* Check that we have a file upload request */
        boolean isMultipart = ServletFileUpload.isMultipartContent(request);
        if (isMultipart == false) {
            logger.warning("[Runner] UPLOAD Bad request");
            String message = "Unable to recognize upload request. Please " + "try again.";
            response.sendError(HttpServletResponse.SC_BAD_REQUEST, message);
            return null;
        }

        // Create a new file upload handler
        ServletFileUpload upload = new ServletFileUpload();

        // Parse the request
        try {
            FileItemIterator iter = upload.getItemIterator(request);
            while (iter.hasNext() == true) {
                FileItemStream item = iter.next();
                String name = item.getName();
                InputStream stream = item.openStream();
                if (item.isFormField() == false) {
                    ContentResource child = (ContentResource) dir.createChild(name, ContentNode.Type.RESOURCE);

                    File tmp = File.createTempFile("contentupload", "tmp");
                    RunUtil.writeToFile(stream, tmp);
                    child.put(tmp);
                    tmp.delete();
                }
            }

            return node;
        } catch (FileUploadException excp) {
            /* Log an error to the log and write an error message back */
            logger.log(Level.WARNING, "[Runner] UPLOAD Failed", excp);
            String message = "Unable to upload runner for some reason.";
            response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, message);
            return null;
        } catch (IOException excp) {
            /* Log an error to the log and write an error message back */
            logger.log(Level.WARNING, "[Runner] UPLOAD Failed", excp);
            String message = "Unable to upload runner for some reason.";
            response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, message);
            return null;
        }
    }

    protected void handleCollection(HttpServletRequest request, HttpServletResponse response, ContentCollection c)
            throws ServletException, IOException, ContentRepositoryException {
        // set the path of this collection
        request.setAttribute("path", c.getPath());

        Collection<DirectoryEntry> entries = new ArrayList<DirectoryEntry>();
        for (ContentNode child : c.getChildren()) {
            DirectoryEntry de = new DirectoryEntry(child);
            switch (de.getType()) {
            case DIRECTORY:
                de.addAction(new DirectoryAction("delete", "delete"));
                break;
            case FILE:
                de.addAction(new DirectoryAction("delete", "delete"));
                break;
            }
            entries.add(de);
        }

        request.setAttribute("entries", entries);
        RequestDispatcher rd = getServletContext().getRequestDispatcher("/browse.jsp");
        rd.forward(request, response);
    }

    protected void handleResource(HttpServletRequest request, HttpServletResponse response, ContentResource r)
            throws ServletException, IOException, ContentRepositoryException {
        // set the type
        String mimeType = getServletContext().getMimeType(r.getName());
        if (mimeType == null) {
            mimeType = "application/octet-stream";
        }
        response.setContentType(mimeType);

        if (r.getSize() > 0) {
            response.setContentLength((int) r.getSize());
        }

        // write the data
        InputStream is = r.getInputStream();
        byte[] buffer = new byte[16 * 1024];
        int read;

        while ((read = is.read(buffer)) > 0) {
            response.getOutputStream().write(buffer, 0, read);
        }

        response.getOutputStream().close();
    }

    // <editor-fold defaultstate="collapsed" desc="HttpServlet methods. Click on the + sign on the left to edit the code.">
    /** 
     * Handles the HTTP <code>GET</code> method.
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    /** 
     * Handles the HTTP <code>POST</code> method.
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    /** 
     * Returns a short description of the servlet.
     * @return a String containing servlet description
     */
    @Override
    public String getServletInfo() {
        return "Short description";
    }// </editor-fold>

    public void contextInitialized(ServletContextEvent sce) {
        // register with the admininstration page
        ServletContext sc = sce.getServletContext();
        ar = new AdminRegistration("Manage Content", "/content-repository/wonderland-content-repository/browse");
        ar.setFilter(AdminRegistration.ADMIN_FILTER);
        AdminRegistration.register(ar, sc);
    }

    public void contextDestroyed(ServletContextEvent sce) {
        // register with the admininstration page
        ServletContext sc = sce.getServletContext();
        AdminRegistration.unregister(ar, sc);
    }

    public static class DirectoryEntry {
        public enum Type {
            FILE, DIRECTORY
        };

        private String name;
        private String path;
        private Type type;
        private List<DirectoryAction> actions;

        public DirectoryEntry(ContentNode node) {
            name = node.getName();

            path = node.getPath();
            if (path.equals("")) {
                path = "/";
            }

            if (node instanceof ContentCollection) {
                type = Type.FILE;
            } else {
                type = Type.DIRECTORY;
            }

            actions = new ArrayList<DirectoryAction>();
        }

        public void addAction(DirectoryAction action) {
            actions.add(action);
        }

        public List<DirectoryAction> getActions() {
            return actions;
        }

        public String getName() {
            return name;
        }

        public String getPath() {
            return path;
        }

        public Type getType() {
            return type;
        }
    }

    public static class DirectoryAction {
        private String name;
        private String url;

        public DirectoryAction(String name, String url) {
            this.name = name;
            this.url = url;
        }

        public String getName() {
            return name;
        }

        public String getUrl() {
            return url;
        }
    }
}