com.lfv.lanzius.server.InfoRequestHandler.java Source code

Java tutorial

Introduction

Here is the source code for com.lfv.lanzius.server.InfoRequestHandler.java

Source

/** 
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program 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
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package com.lfv.lanzius.server;

import com.lfv.lanzius.Constants;
import com.lfv.lanzius.DomTools;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.logging.Log;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
import org.apache.velocity.exception.MethodInvocationException;
import org.apache.velocity.exception.ParseErrorException;
import org.apache.velocity.exception.ResourceNotFoundException;
import org.jdom.Document;
import org.jdom.Element;
import org.mortbay.jetty.HttpConnection;
import org.mortbay.jetty.Request;
import org.mortbay.jetty.handler.AbstractHandler;

/**
 * The InfoRequestHandler is handling the /xml context path of the http server. It
 * uses the template engine Velocity (http://jakarta.apache.org/velocity) to
 * build up xml files from document.
 */
public class InfoRequestHandler extends AbstractHandler {

    private LanziusServer server;
    private Template userTemplate;
    private List<Role> roleDefsList;
    private Log log;

    /**
     * Create a new instance of InfoRequestHandler.
     *
     */
    public InfoRequestHandler(LanziusServer server, Log log) throws Exception {
        this.server = server;
        this.log = log;
        userTemplate = Velocity.getTemplate("data/resources/player.vm");
    }

    /**
     * Handle an incoming http request and let the Velocity module create the
     * response from user and channel structures and xml templates located on
     * the server data/resources folder.
     *
     */
    public void handle(String target, HttpServletRequest request, HttpServletResponse response, int dispatch)
            throws IOException, ServletException {
        Request base_request = (request instanceof Request) ? (Request) request
                : HttpConnection.getCurrentConnection().getRequest();
        log.debug("Incoming request: " + target);

        // Create a velocity context
        VelocityContext context = new VelocityContext();

        // Get output writer
        PrintWriter writer = response.getWriter();
        try {
            base_request.setHandled(true);
            if (target.equals("/info")) {
                Document doc = server.getDocument();

                if (doc == null || !server.isServerStarted()) {
                    log.warn("Trying to get info from xml server but the server is not started yet!");
                    response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
                } else {
                    String tid_s = request.getParameter("terminal");
                    log.debug("Incoming info request for terminal: " + tid_s);

                    // Lists for velocity merge
                    List<Channel> channelList = new LinkedList<Channel>();
                    List<Role> roleList = new LinkedList<Role>();

                    synchronized (doc) {
                        // Get Player element from PlayerSetup
                        Element ep = DomTools.getElementFromSection(doc, "PlayerSetup", "terminalid", tid_s);
                        if (ep != null) {
                            int gid = DomTools.getAttributeInt(ep, "groupid", 0, true);

                            // Names, Group and Codec
                            context.put("TerminalName",
                                    DomTools.getChildText(
                                            DomTools.getElementFromSection(doc, "TerminalDefs", "id", tid_s),
                                            "Name", "T/" + tid_s, false));
                            context.put("PlayerName", DomTools.getChildText(ep, "Name", "", false));
                            context.put("Group", DomTools.getChildText(
                                    DomTools.getElementFromSection(doc, "GroupDefs", "id", String.valueOf(gid)),
                                    "Name", "G/" + gid, false));
                            context.put("Codec",
                                    DomTools.getAttributeString(doc.getRootElement(), "codec", "null", false));

                            // Role defs list
                            if (roleDefsList == null) {
                                roleDefsList = new LinkedList<Role>();
                                // Populate
                                Iterator iter = doc.getRootElement().getChild("RoleDefs").getChildren().iterator();
                                while (iter.hasNext()) {
                                    Element er = (Element) iter.next();
                                    int id = DomTools.getAttributeInt(er, "id", 0, false);
                                    if (id > 0) {
                                        Role r = new Role(DomTools.getChildText(er, "Name", "Withheld", false));
                                        r.setId(id);
                                        roleDefsList.add(r);
                                    }
                                }
                            }

                            context.put("RoleDefsList", roleDefsList);

                            // Channels
                            boolean addedMonitor = false;
                            Element ecs = ep.getChild("ChannelSetup");
                            Iterator iter = ecs.getChildren().iterator();
                            while (iter.hasNext()) {
                                Element ecr = (Element) iter.next();
                                int cid = DomTools.getAttributeInt(ecr, "id", 0, true);
                                Element ec = DomTools.getElementFromSection(doc, "ChannelDefs", "id",
                                        String.valueOf(cid));
                                if (ec != null) {
                                    // Collect all attributes and textnodes into the Channel struct
                                    // with correct attribute priority:
                                    // high:  Channel node under ChannelSetup
                                    // med:   Channel node under ChannelDefs
                                    // low:   Player (groupId)
                                    Channel ch = new Channel(DomTools.getChildText(ec, "Name", "C/" + cid, false));

                                    // Calculate which group the channel belongs to and set client cid
                                    int gidc = DomTools.getPrioritizedAttribute("groupid", gid, ecr, ec);
                                    ch.setId((gidc << Constants.ID_BITSHIFT) | cid);

                                    // All other attrs
                                    ch.setState(DomTools.getPrioritizedAttribute("state", "off", ecr, ec));
                                    ch.setLocked(DomTools.getPrioritizedAttribute("locked", "false", ecr, ec));
                                    ch.setRecordable(
                                            DomTools.getPrioritizedAttribute("recordable", "false", ecr, ec));
                                    ch.setHidden(DomTools.getPrioritizedAttribute("hidden", "false", ecr, ec));
                                    ch.setMonitor(DomTools.getPrioritizedAttribute("monitor", "false", ecr, ec));

                                    // Prevent duplicate monitors and monitor and state rxtx combination
                                    if (ch.getMonitor().equals("true")) {
                                        if (addedMonitor) {
                                            ch.setMonitor("false");
                                        } else {
                                            if (ch.getState().equals("rxtx")) {
                                                ch.setState("rx");
                                            }
                                            addedMonitor = true;
                                        }
                                    }

                                    // Show group name on channel?
                                    if (DomTools.getPrioritizedAttribute("showgroup", "false", ecr, ec)
                                            .equals("true")) {
                                        String groupName = DomTools.getChildText(DomTools.getElementFromSection(doc,
                                                "GroupDefs", "id", String.valueOf(gidc)), "Name", "G/" + gidc,
                                                false);
                                        ch.setName(groupName + "/" + ch.getName());
                                    }

                                    channelList.add(ch);
                                } else
                                    log.error("Missing Channel node in ChannelDefs (" + cid + ")");
                            }

                            // Roles
                            Element ers = ep.getChild("RoleSetup");
                            iter = ers.getChildren().iterator();
                            while (iter.hasNext()) {
                                Element err = (Element) iter.next();
                                int rid = DomTools.getAttributeInt(err, "id", 0, false);

                                // Empty slot
                                if (rid == 0) {
                                    roleList.add(new Role("empty_slot"));
                                } else {
                                    Element er = DomTools.getElementFromSection(doc, "RoleDefs", "id",
                                            String.valueOf(rid));
                                    Role r = new Role(DomTools.getChildText(er, "Name", "R/" + rid, false));

                                    int uid = DomTools.getAttributeInt(err, "uid", 0, true);

                                    // Debug check, calculate which group the role belongs to (already done in linkTerminal)
                                    int uidc = (DomTools.getPrioritizedAttribute("groupid", gid, err,
                                            er) << Constants.ID_BITSHIFT) | rid;
                                    if (uid != uidc)
                                        log.error("UIDs mismatch when requesting xml info (" + uid + " != " + uidc
                                                + ")");

                                    //  Set client rid
                                    r.setId(uid);

                                    // Peers
                                    List<Peer> l = r.getPeerList();
                                    Element eps = er.getChild("PhoneSetup");
                                    if (eps != null) {
                                        Iterator iter2 = eps.getChildren().iterator();
                                        while (iter2.hasNext()) {
                                            Element erpr = (Element) iter2.next();
                                            int rpid = DomTools.getAttributeInt(erpr, "id", 0, false);

                                            // Empty slot
                                            if (rpid == 0) {
                                                l.add(new Peer("empty_slot"));
                                            } else {
                                                Element erp = DomTools.getElementFromSection(doc, "RoleDefs", "id",
                                                        String.valueOf(rpid));
                                                Peer p = new Peer(
                                                        DomTools.getChildText(erp, "Name", "R/" + rpid, false));

                                                // Calculate which group the role belongs to and set client rpid
                                                int gidc = DomTools.getPrioritizedAttribute("groupid", gid, erpr,
                                                        erp);
                                                p.setId((gidc << Constants.ID_BITSHIFT) | rpid);

                                                // Show group name on peer?
                                                if (DomTools
                                                        .getPrioritizedAttribute("showgroup", "false", erpr, erp)
                                                        .equals("true")) {
                                                    String groupName = DomTools.getChildText(
                                                            DomTools.getElementFromSection(doc, "GroupDefs", "id",
                                                                    String.valueOf(gidc)),
                                                            "Name", "G/" + gidc, false);
                                                    p.setName(groupName + "/" + p.getName());
                                                }

                                                // Add to phone peer list, never add self!
                                                if (r.getId() != p.getId())
                                                    l.add(p);
                                            }
                                        }
                                    } else
                                        log.warn("Missing PhoneSetup for Role " + rid + "!");

                                    roleList.add(r);
                                }
                            }
                        } else {
                            log.warn("Incoming info request for a terminal that does not exist (" + tid_s + ")");
                            context.put("Name", "Unknown");
                            context.put("Group", "Unknown");
                            context.put("Codec", "Unknown");
                        }
                    }

                    context.put("ChannelList", channelList);
                    context.put("RoleList", roleList);

                    userTemplate.merge(context, writer);
                }
            } else if (target.equals("/isa")) {
                log.debug("Received ISA request");
                response.sendError(HttpServletResponse.SC_OK);
                int terminalId = Integer.parseInt(request.getParameter("terminal"));
                int value = Integer.parseInt(request.getParameter("val"));
                int time = Integer.parseInt(request.getParameter("t"));
                log.debug("ISA request, terminal = " + terminalId + ", val = " + value + ", time = " + time);
                server.addIsaValue(terminalId, value, time);
            } else
                response.sendError(HttpServletResponse.SC_NOT_FOUND);
        } catch (ResourceNotFoundException ex) {
            log.error("Resource not found", ex);
            response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
        } catch (ParseErrorException ex) {
            log.error("Parse Error", ex);
            response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
        } catch (MethodInvocationException ex) {
            log.error("Method Invocation Error", ex);
            response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
        } catch (Exception ex) {
            log.error("Exception in request! Correct configuration?", ex);
            response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
        }

        writer.close();
    }

    public class Channel {

        private int id;
        private String state;
        private String locked;
        private String recordable;
        private String hidden;
        private String name;
        private String monitor;

        private Channel(String name) {
            this.name = name;
        }

        public int getId() {
            return id;
        }

        public String getState() {
            return state;
        }

        public String getLocked() {
            return locked;
        }

        public String getRecordable() {
            return recordable;
        }

        public String getHidden() {
            return hidden;
        }

        public String getName() {
            return name;
        }

        public String getMonitor() {
            return monitor;
        }

        private void setId(int id) {
            this.id = id;
        }

        private void setState(String state) {
            this.state = state;
        }

        private void setLocked(String locked) {
            this.locked = locked;
        }

        private void setRecordable(String recordable) {
            this.recordable = recordable;
        }

        private void setHidden(String hidden) {
            this.hidden = hidden;
        }

        private void setName(String name) {
            this.name = name;
        }

        private void setMonitor(String monitor) {
            this.monitor = monitor;
        }
    }

    public class Role {
        private int id;
        private String name;
        private List<Peer> peerList;

        private Role(String name) {
            this.name = name;
            peerList = new LinkedList<Peer>();
        }

        public int getId() {
            return id;
        }

        public String getName() {
            return name;
        }

        public List<Peer> getPeerList() {
            return peerList;
        }

        private void setId(int id) {
            this.id = id;
        }
    }

    public class Peer {
        private int id;
        private String name;

        private Peer(String name) {
            this.name = name;
        }

        public int getId() {
            return id;
        }

        public String getName() {
            return name;
        }

        private void setId(int id) {
            this.id = id;
        }

        private void setName(String name) {
            this.name = name;
        }
    }
}