Package org.jdesktop.wonderland.modules.snapshot.web.servlet

Source Code of org.jdesktop.wonderland.modules.snapshot.web.servlet.SnapshotManagerServlet$EmptyWorld

/**
* Open Wonderland
*
* Copyright (c) 2012, Open Wonderland Foundation, 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.
*
* The Open Wonderland Foundation designates this particular file as subject to
* the "Classpath" exception as provided by the Open Wonderland Foundation in
* the License file that accompanied this code.
*/

/**
* 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.snapshot.web.servlet;

import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.servlet.RequestDispatcher;
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.jdesktop.wonderland.front.admin.AdminRegistration;
import org.jdesktop.wonderland.front.admin.StatusPageRegistration;
import org.jdesktop.wonderland.modules.darkstar.api.weblib.DarkstarRunner;
import org.jdesktop.wonderland.runner.RunManager;
import org.jdesktop.wonderland.tools.wfs.WFS;
import org.jdesktop.wonderland.web.wfs.WFSManager;
import org.jdesktop.wonderland.web.wfs.WFSSnapshot;
import org.jdesktop.wonderland.runner.Runner.Status;
import org.jdesktop.wonderland.runner.RunnerException;
import org.jdesktop.wonderland.runner.StatusWaiter;
import org.jdesktop.wonderland.web.wfs.WFSRoot;

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

    // the empty world
    private static final EmptyWorld EMPTY_WORLD = new EmptyWorld();

    // our registration with the webadmin system
    private AdminRegistration reg;

    private StatusPageRegistration statusRegistry;
   
    /**
     * 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
    {
        WFSManager m = WFSManager.getWFSManager();

        String action = request.getParameter("action");
        if (action == null) {
            action = "view";
        }

        WFSRoot root = getRoot(request);
        WFSSnapshot snapshot = null;
        if (root instanceof WFSSnapshot) {
            snapshot = (WFSSnapshot) root;
        }

        SnapshotResult result = null;
        if (action.equalsIgnoreCase("update")) {
            result = doUpdate(request, response, snapshot);
        } else if (action.equalsIgnoreCase("edit")) {
            result = doEdit(request, response, snapshot);
        } else if (action.equalsIgnoreCase("remove")) {
            result = doRemove(request, response, snapshot);
        } else if (action.equalsIgnoreCase("snapshot")) {
            result = doSnapshot(request, response);
        } else if (action.equalsIgnoreCase("current")) {
            result = doCurrent(request, response, root);
        } else if (action.equalsIgnoreCase("restore")) {
            result = doRestore(request, response, root);
        }

        if (result != null) {
            // make the error visible
            request.setAttribute("error", result.getError());
            if (result.hasError()) {
                logger.warning("Error processing action " + action + ": " +
                               result.getError());
            }

            // redirect to the requested page
            if (result.hasRedirect()) {
                RequestDispatcher rd = getServletContext().getRequestDispatcher(result.getRedirect());
                rd.forward(request, response);
                return;
            }
        }

        // if we get here, we are going to display the main page

        // store the wfs roots in a variable
        List<WFSRoot> wfsRoots = m.getWFSRoots();
        wfsRoots.add(0, EMPTY_WORLD);
        request.setAttribute("roots", wfsRoots);

        // store the wfs snapshots in a variable.  Sort the snapshots by date
        List<WFSSnapshot> snapshots = m.getWFSSnapshots();
        Collections.sort(snapshots, new Comparator<WFSSnapshot>() {
            public int compare(WFSSnapshot o1, WFSSnapshot o2) {
                if (o1.getTimestamp() == null) {
                    return (o2.getTimestamp() == null)?0:1;
                } else if (o2.getTimestamp() == null) {
                    return -1;
                }
               
                return -1 * o1.getTimestamp().compareTo(o2.getTimestamp());
            }           
        });
        request.setAttribute("snapshots", snapshots);

        // find the current snapshot
        WFSRoot currentRoot = getCurrentRoot(wfsRoots, snapshots);
        request.setAttribute("currentroot", currentRoot);

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

    SnapshotResult doEdit(HttpServletRequest request,
                          HttpServletResponse response,
                          WFSSnapshot snapshot)
        throws ServletException, IOException
    {
        if (snapshot == null) {
            return new SnapshotResult("No such snapshot " +
                                      request.getParameter("root"),
                                      null);
        }
        request.setAttribute("snapshot", snapshot);

        return new SnapshotResult(null, "/edit.jsp");
    }

    SnapshotResult doUpdate(HttpServletRequest request,
                            HttpServletResponse response,
                            WFSSnapshot snapshot)
        throws ServletException, IOException
    {
        if (snapshot == null) {
            return new SnapshotResult("No such snapshot " +
                                      request.getParameter("root"),
                                      "/edit.jsp");
        }

        logger.info("User " + getUsername(request) + " updated snapshot " +
                    snapshot.getRootPath());

        String name = request.getParameter("name");
        if (name == null) {
            name = "";
        }

        String description = request.getParameter("description");
        if (description == null) {
            description = "";
        }

        if (!name.equals(snapshot.getName())) {
            // change the name
            String error = validName(name, snapshot);
            if (error != null) {
                return new SnapshotResult(error, "/edit.jsp");
            }

            snapshot.setName(name);
        }

        if (!description.equals(snapshot.getDescription())) {
            snapshot.setDescription(description);
        }

        return null;
    }

    SnapshotResult doRemove(HttpServletRequest request,
                            HttpServletResponse response,
                            WFSSnapshot snapshot)
        throws ServletException, IOException
    {
        if (snapshot == null) {
            return new SnapshotResult("No such snapshot " +
                                      request.getParameter("root"),
                                      null);
        }

        logger.info("User " + getUsername(request) + " removed snapshot " +
                    snapshot.getRootPath());

        WFSManager.getWFSManager().removeWFSSnapshot(snapshot.getName());
        return null;
    }

    SnapshotResult doSnapshot(HttpServletRequest request,
                              HttpServletResponse response)
        throws ServletException, IOException
    {
        // get the name from the request
        String name = request.getParameter("name");
        if (name == null) {
            // use a default name based on the current data
            DateFormat df = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss.SS");
            name = df.format(new Date());
        }

        logger.info("User " + getUsername(request) + " created snapshot " +
                    name);

        DarkstarRunner runner = getRunner();

        // make sure the runner is stopped
        SnapshotResult res = requestRestart(request, runner, "snapshot");
        if (res != null) {
            return res;
        }

        try {
            runner.createSnapshot(name);
        } catch (RunnerException re) {
            throw new ServletException(re);
        }

        completeRestart(request, runner);
        return null;
    }

    SnapshotResult doCurrent(HttpServletRequest request,
                             HttpServletResponse response,
                             WFSRoot root)
        throws ServletException, IOException
    {
        logger.info("User " + getUsername(request) + " set current snapshot " +
                    "to " + root.getRootPath());

        DarkstarRunner runner = getRunner();

        // make sure the runner is stopped
        SnapshotResult res = requestRestart(request, runner, "current&root=" +
                                            getRootName(root));
        if (res != null) {
            return res;
        }

        // set the name
        runner.setWFSName(root.getRootPath());

        // finsh restarting
        completeRestart(request, runner);
        return null;
    }

    SnapshotResult doRestore(HttpServletRequest request,
                             HttpServletResponse response,
                             WFSRoot root)
        throws ServletException, IOException
    {
        logger.info("User " + getUsername(request) + " restored snapshot " +
                    root.getRootPath());

        DarkstarRunner runner = getRunner();

        // make sure the runner is stopped
        SnapshotResult res = requestRestart(request, runner, "restore&root=" +
                                            getRootName(root));
        if (res != null) {
            return res;
        }

        // set the name
        runner.setWFSName(root.getRootPath());
        runner.forceColdstart();

        // complete the restart
        completeRestart(request, runner);
        return null;
    }

    /**
     * Request that the given runner be stopped.
     * @param request the http request
     * @param runner the runner to stop
     * @param action the current action
     * @return null if the runner is stopped, or a SnapshotResult to go
     * to if the runner is not stopped
     */
    SnapshotResult requestRestart(HttpServletRequest request,
                                  DarkstarRunner runner,
                                  String action)
        throws IOException, ServletException
    {
        // make sure the runner exists
        if (runner == null) {
            return new SnapshotResult("No Darkstar servers available", null);
        }

        // find out whether we can stop the server
        boolean restart = false;
        String restartStr = request.getParameter("restart");
        if (restartStr != null) {
            restart = Boolean.parseBoolean(restartStr);
        }

        if (runner.getStatus() != Status.NOT_RUNNING) {
            if (restart) {
                try {
                    // stop the runner, and wait for it to stop
                    StatusWaiter sw = RunManager.getInstance().stop(runner, true);
                    sw.waitFor();
                } catch (RunnerException re) {
                    logger.log(Level.WARNING, "Error stopping " + runner, re);
                    return new SnapshotResult("Error stopping runner", null);
                } catch (InterruptedException ie) {
                    // just ignore?
                    logger.log(Level.WARNING, "Status wait interrupted", ie);
                }
            } else {
                // forward to the confim page
                request.setAttribute("prompt", "The Darkstar server must " +
                    "be restarted to perform this action");
                request.setAttribute("url", "?action=" + action + "&restart=true");
                return new SnapshotResult(null, "/confirm.jsp");
            }
        }

        // everything is OK
        return null;
    }

    /**
     * Complete a previous restart request
     * @param request the request
     * @param runner the runner to restart
     */
    protected void completeRestart(HttpServletRequest request,
                                   DarkstarRunner runner)
        throws IOException, ServletException
    {
        // make sure the runner exists
        if (runner == null) {
            return;
        }

        // find out whether we can stop the server
        boolean restart = false;
        String restartStr = request.getParameter("restart");
        if (restartStr != null) {
            restart = Boolean.parseBoolean(restartStr);
        }

        // start back up
        if (runner.getStatus() == Status.NOT_RUNNING) {
            if (restart) {
                // start the runner, don't wait for it though
                try {
                    RunManager.getInstance().start(runner, false);
                } catch (RunnerException re) {
                    throw new ServletException(re);
                }
            }
        }
    }

    /**
     * Get a WFS root from the request
     * @param request the request to get the root from
     */
    protected WFSRoot getRoot(HttpServletRequest request) {
        WFSRoot root = null;

        String rootName = request.getParameter("root");
        if (rootName == null) {
            return null;
        }

        // decide if it is a world or a snapshot
        if (rootName.startsWith(WFSRoot.WORLDS_DIR)) {
            String worldName = rootName.substring(WFSRoot.WORLDS_DIR.length() + 1);
            if (worldName.equals(EMPTY_WORLD.getName())) {
                return EMPTY_WORLD;
            }
           
            root = WFSManager.getWFSManager().getWFSRoot(worldName);
        } else if (rootName.startsWith(WFSSnapshot.SNAPSHOTS_DIR)) {
            String snapshotName = rootName.substring(WFSSnapshot.SNAPSHOTS_DIR.length() + 1);
            root = WFSManager.getWFSManager().getWFSSnapshot(snapshotName);
        }

        if (root == null) {
            logger.warning("Unable to find root: " + rootName);
        }

        return root;
    }

    /**
     * Get the name of a root
     * @param root the root to get the name of
     * @return the root name
     */
    protected String getRootName(WFSRoot root) {
        if (root instanceof WFSSnapshot) {
            return WFSSnapshot.SNAPSHOTS_DIR + "/" + root.getName();
        } else {
            return WFSRoot.WORLDS_DIR + "/" + root.getName();
        }
    }

    /**
     * Get the current WFS snapshot
     * @return the current snapshot
     */
    protected WFSRoot getCurrentRoot(List<WFSRoot> roots,
                                     List<WFSSnapshot> snapshots)
    {
        DarkstarRunner dr = getRunner();
        if (dr == null) {
            return null;
        }

        System.out.println("Get current root: " + dr.getWFSName());

        if (dr.getWFSName() == null) {
            return EMPTY_WORLD;
        }

        for (WFSRoot root : roots) {
            if (root.getRootPath().equals(dr.getWFSName())) {
                return root;
            }
        }

        for (WFSRoot root : snapshots) {
            if (root.getRootPath().equals(dr.getWFSName())) {
                return root;
            }
        }

        // not found
        return null;
    }

    /**
     * Get a Darkstar runner.  For now, this returns the first valid
     * runner.
     * XXX TODO: Deal with multiple runners XXX
     * @return the runner, or null if no Darkstar runner exists
     */
    protected DarkstarRunner getRunner() {
        Collection<DarkstarRunner> runners =
                RunManager.getInstance().getAll(DarkstarRunner.class);
        if (runners.isEmpty()) {
            return null;
        }

        return runners.iterator().next();
    }

    /**
     * Return any errors changing the given snapshot to the given name,
     * or null if there are no errors.
     */
    protected String validName(String name, WFSSnapshot snapshot) {
        if (name == null || name.trim().length() == 0) {
            return "Blank name";
        } else if (name.contains(" ") || name.contains("\t")) {
            return "Spaces not allowed in name";
        } else if (WFSManager.getWFSManager().getWFSSnapshot(name) != null) {
            return "Duplicate snapshot " + name;
        } else {
            return null;
        }
    }

    /**
     * Get the name of the current user, or "unknown" for an unauthenticated user
     * @return the username, or "unknown"
     */
    public String getUsername(HttpServletRequest req) {
        if (req.getUserPrincipal() == null) {
            return "unknown";
        }

        return req.getUserPrincipal().getName();
    }

    // <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 web admin
        reg = new AdminRegistration("Manage Worlds",
                                    "/snapshot-manager/snapshot/SnapshotManager");
        reg.setFilter(AdminRegistration.ADMIN_FILTER);
        AdminRegistration.register(reg, sce.getServletContext());
       
        statusRegistry = new StatusPageRegistration("/snapshot-manager/snapshot", "/current.jspf");
        StatusPageRegistration.register(statusRegistry, sce.getServletContext());
    }

    public void contextDestroyed(ServletContextEvent sce) {
        // unregister
        AdminRegistration.unregister(reg, sce.getServletContext());
        StatusPageRegistration.unregister(statusRegistry, sce.getServletContext());
    }

    class SnapshotResult {
        private String error;
        private String redirect;

        SnapshotResult(String error, String redirect) {
            this.error = error;
            this.redirect = redirect;
        }

        boolean hasError() {
            return error != null;
        }

        String getError() {
            return error;
        }

        boolean hasRedirect() {
            return redirect != null;
        }

        String getRedirect() {
            return redirect;
        }
    }

    static class EmptyWorld extends WFSRoot {
        @Override
        public String getName() {
            return "Empty World";
        }

        @Override
        public String getRootPath() {
            return "none";
        }

        @Override
        public WFS getWfs() {
            return null;
        }
    }
}
TOP

Related Classes of org.jdesktop.wonderland.modules.snapshot.web.servlet.SnapshotManagerServlet$EmptyWorld

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.