org.unitime.timetable.server.menu.MenuBackend.java Source code

Java tutorial

Introduction

Here is the source code for org.unitime.timetable.server.menu.MenuBackend.java

Source

/*
 * UniTime 3.5 (University Timetabling Application)
 * Copyright (C) 2014, UniTime LLC, and individual contributors
 * as indicated by the @authors tag.
 * 
 * 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 org.unitime.timetable.server.menu;

import java.io.File;
import java.net.URL;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import javax.servlet.ServletException;

import org.apache.log4j.Logger;
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.unitime.localization.impl.Localization;
import org.unitime.localization.messages.PageNames;
import org.unitime.timetable.ApplicationProperties;
import org.unitime.timetable.action.PersonalizedExamReportAction;
import org.unitime.timetable.defaults.ApplicationProperty;
import org.unitime.timetable.gwt.command.client.GwtRpcException;
import org.unitime.timetable.gwt.command.client.GwtRpcResponseList;
import org.unitime.timetable.gwt.command.server.GwtRpcImplementation;
import org.unitime.timetable.gwt.command.server.GwtRpcImplements;
import org.unitime.timetable.gwt.shared.MenuInterface;
import org.unitime.timetable.gwt.shared.MenuInterface.MenuRpcRequest;
import org.unitime.timetable.model.Roles;
import org.unitime.timetable.model.SavedHQL;
import org.unitime.timetable.model.SolverGroup;
import org.unitime.timetable.model.dao.SessionDAO;
import org.unitime.timetable.security.SessionContext;
import org.unitime.timetable.security.UserAuthority;
import org.unitime.timetable.security.UserContext;
import org.unitime.timetable.security.qualifiers.SimpleQualifier;
import org.unitime.timetable.security.rights.Right;
import org.unitime.timetable.solver.service.SolverServerService;
import org.unitime.timetable.util.RoomAvailability;
import org.xml.sax.EntityResolver;
import org.xml.sax.InputSource;

/**
 * @author Tomas Muller
 */
@GwtRpcImplements(MenuRpcRequest.class)
public class MenuBackend
        implements GwtRpcImplementation<MenuRpcRequest, GwtRpcResponseList<MenuInterface>>, InitializingBean {
    private static Logger sLog = Logger.getLogger(MenuBackend.class);
    protected Element iRoot = null;
    private static PageNames sPageNames = Localization.create(PageNames.class);

    @Autowired
    private SolverServerService solverServerService;

    @Autowired
    private SessionContext sessionContext;

    @Override
    public void afterPropertiesSet() throws Exception {
        try {
            String menu = ApplicationProperty.MenuFile.value();
            Document document = null;
            URL menuUrl = ApplicationProperties.class.getClassLoader().getResource(menu);
            SAXReader sax = new SAXReader();
            sax.setEntityResolver(new EntityResolver() {
                public InputSource resolveEntity(String publicId, String systemId) {
                    if (publicId.equals("-//UniTime//UniTime Menu DTD/EN")) {
                        return new InputSource(
                                ApplicationProperties.class.getClassLoader().getResourceAsStream("menu.dtd"));
                    }
                    return null;
                }
            });
            if (menuUrl != null) {
                sLog.info("Reading menu from " + URLDecoder.decode(menuUrl.getPath(), "UTF-8") + " ...");
                document = sax.read(menuUrl.openStream());
            } else if (new File(menu).exists()) {
                sLog.info("Reading menu from " + menu + " ...");
                document = sax.read(new File(menu));
            }
            if (document == null)
                throw new ServletException("Unable to create menu, reason: resource " + menu + " not found.");

            if (!"unitime-menu".equals(document.getRootElement().getName()))
                throw new ServletException("Menu has an unknown format.");
            iRoot = document.getRootElement();

            String customMenu = ApplicationProperty.CustomMenuFile.value();
            Document customDocument = null;
            URL customMenuUrl = ApplicationProperties.class.getClassLoader().getResource(customMenu);
            if (customMenuUrl != null) {
                sLog.info(
                        "Reading custom menu from " + URLDecoder.decode(customMenuUrl.getPath(), "UTF-8") + " ...");
                customDocument = sax.read(customMenuUrl.openStream());
            } else if (new File(customMenu).exists()) {
                sLog.info("Reading custom menu from " + customMenu + " ...");
                customDocument = sax.read(new File(customMenu));
            }
            if (customDocument != null) {
                merge(iRoot, customDocument.getRootElement());
            }

        } catch (Exception e) {
            if (e instanceof RuntimeException)
                throw (RuntimeException) e;
            throw new RuntimeException("Unable to initialize, reason: " + e.getMessage(), e);
        }
    }

    @Override
    public GwtRpcResponseList<MenuInterface> execute(MenuRpcRequest request, SessionContext context) {
        try {
            org.hibernate.Session hibSession = SessionDAO.getInstance().getSession();
            try {
                GwtRpcResponseList<MenuInterface> menu = new GwtRpcResponseList<MenuInterface>();
                if (iRoot == null)
                    throw new GwtRpcException("menu is not configured properly");

                for (Iterator<Element> i = iRoot.elementIterator(); i.hasNext();) {
                    Element element = i.next();
                    MenuInterface m = getMenu(element);
                    if (m != null)
                        menu.add(m);
                }

                if (menu.isEmpty())
                    throw new GwtRpcException("no menu");

                return menu;
            } finally {
                hibSession.close();
            }
        } catch (GwtRpcException e) {
            throw e;
        } catch (Exception e) {
            throw new GwtRpcException(e.getMessage());
        }
    }

    private void merge(Element menu, Element custom) {
        if ("remove".equals(custom.getName())) {
            menu.getParent().remove(menu);
            return;
        }
        for (Iterator<Attribute> i = custom.attributeIterator(); i.hasNext();) {
            Attribute a = i.next();
            menu.addAttribute(a.getName(), a.getValue());
        }
        for (Iterator<Element> i = custom.elementIterator(); i.hasNext();) {
            Element e = i.next();
            if ("parameter".equals(e.getName())) {
                for (Iterator<Element> j = menu.elementIterator("parameter"); j.hasNext();) {
                    menu.remove(j.next());
                }
                menu.add(e.createCopy());
                continue;
            }
            if ("condition".equals(e.getName())) {
                menu.add(e.createCopy());
                continue;
            }
            if ("new-condition".equals(e.getName())) {
                for (Iterator<Element> j = menu.elementIterator("condition"); j.hasNext();) {
                    menu.remove(j.next());
                }
                Element f = e.createCopy();
                f.setName("condition");
                menu.add(f);
                continue;
            }
            String name = e.attributeValue("name");
            Element x = null;
            if (name != null) {
                for (Iterator<Element> j = menu.elementIterator(); j.hasNext();) {
                    Element f = j.next();
                    if (name.equals(f.attributeValue("name"))) {
                        x = f;
                        break;
                    }
                }
            }
            if (x != null) {
                merge(x, e);
            } else {
                int pos = Integer.parseInt(e.attributeValue("position", "-1"));
                if (pos >= 0) {
                    List<Element> after = new ArrayList<Element>();
                    for (Iterator<Element> j = menu.elementIterator(); j.hasNext();) {
                        Element f = j.next();
                        if ("condition".equals(f.getName()))
                            continue;
                        if (pos > 0) {
                            pos--;
                        } else {
                            after.add(f);
                            menu.remove(f);
                        }
                    }
                    menu.add(e.createCopy());
                    for (Element f : after)
                        menu.add(f);
                } else
                    menu.add(e.createCopy());
            }
        }
    }

    private MenuInterface getMenu(Element menuElement) {
        try {
            MenuInterface menu = new MenuInterface();
            String name = menuElement.attributeValue("name");
            String localizedName = (name == null ? null
                    : sPageNames.translateMessage(
                            name.trim().replace(' ', '_').replace("(", "").replace(")", "").replace(':', '_'),
                            null));
            menu.setName(localizedName == null ? name : localizedName);
            menu.setTitle(menuElement.attributeValue("title"));
            menu.setTarget(menuElement.attributeValue("target"));
            menu.setPage(menuElement.attributeValue("page"));
            menu.setHash(menuElement.attributeValue("hash"));
            String type = menuElement.attributeValue("type");
            if ("gwt".equals(type))
                menu.setGWT(true);
            if ("property".equals(type) && menu.getPage() != null) {
                menu.setPage(ApplicationProperties.getProperty(menu.getPage()));
                if (menu.getPage() == null)
                    return null;
            }

            boolean sep = true;
            for (Iterator<Element> i = menuElement.elementIterator(); i.hasNext();) {
                Element element = i.next();
                if ("condition".equals(element.getName())) {
                    if (!check(element))
                        return null;
                } else if ("parameter".equals(element.getName())) {
                    menu.addParameter(element.attributeValue("name"),
                            element.attributeValue("value", element.getText()));
                } else {
                    MenuInterface m = getMenu(element);
                    if (m != null) {
                        if (sep && m.isSeparator())
                            continue;
                        menu.addSubMenu(m);
                        sep = m.isSeparator();
                    }
                }
            }
            while (menu.hasSubMenus() && menu.getSubMenus().get(menu.getSubMenus().size() - 1).isSeparator())
                menu.getSubMenus().remove(menu.getSubMenus().size() - 1);
            return (menu.isSeparator() || menu.hasPage() || menu.hasSubMenus() ? menu : null);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    private boolean check(Element conditionElement) {
        String cond = conditionElement.getName();
        if ("and".equals(cond) || "condition".equals(cond)) {
            for (Iterator<Element> i = conditionElement.elementIterator(); i.hasNext();) {
                Element element = i.next();
                if (!check(element))
                    return false;
            }
            return true;
        } else if ("or".equals(cond)) {
            for (Iterator<Element> i = conditionElement.elementIterator(); i.hasNext();) {
                Element element = i.next();
                if (check(element))
                    return true;
            }
            return false;
        } else if ("not".equals(cond)) {
            for (Iterator<Element> i = conditionElement.elementIterator(); i.hasNext();) {
                Element element = i.next();
                if (check(element))
                    return false;
            }
            return true;
        } else if ("isAuthenticated".equals(cond)) {
            return sessionContext.isAuthenticated();
        } else if ("hasRole".equals(cond)) {
            UserContext user = sessionContext.getUser();
            if (user == null)
                return false;
            String role = conditionElement.attributeValue("name");
            if (role == null)
                return sessionContext.hasPermission(Right.HasRole);
            ; // has any role
            if (user.getCurrentAuthority() == null)
                return Roles.ROLE_ANONYMOUS.equals(role);
            else
                return role.equalsIgnoreCase(user.getCurrentAuthority().getRole());
        } else if ("propertyEquals".equals(cond)) {
            return conditionElement.attributeValue("value", "true").equalsIgnoreCase(
                    ApplicationProperties.getProperty(conditionElement.attributeValue("name", "dummy"),
                            conditionElement.attributeValue("defaultValue", "false")));
        } else if ("hasProperty".equals(cond)) {
            return ApplicationProperties.getProperty(conditionElement.attributeValue("name", "dummy")) != null;
        } else if ("hasPermission".equals(cond)) {
            Right right = null;
            try {
                right = Right.valueOf(conditionElement.attributeValue("name"));
            } catch (IllegalArgumentException e) {
                sLog.warn("Unknown right: " + conditionElement.attributeValue("name"));
            }
            if (right == null)
                return false;
            String authority = conditionElement.attributeValue("authority", "current");
            if ("session".equals(authority)) {
                Long sessionId = (sessionContext.isAuthenticated()
                        ? sessionContext.getUser().getCurrentAcademicSessionId()
                        : null);
                return (sessionId == null ? false
                        : sessionContext.hasPermissionAnyAuthority(right,
                                new SimpleQualifier("Session", sessionId)));
            } else if ("role".equals(authority)) {
                UserAuthority ua = (sessionContext.isAuthenticated()
                        ? sessionContext.getUser().getCurrentAuthority()
                        : null);
                String role = (ua != null ? ua.getRole() : null);
                return (role == null ? false
                        : sessionContext.hasPermissionAnyAuthority(right, new SimpleQualifier("Role", role)));
            } else if ("any".equals(authority)) {
                return sessionContext.hasPermissionAnyAuthority(right);
            } else {
                return sessionContext.hasPermission(right);
            }
        } else if ("hasRight".equals(cond)) {
            String right = conditionElement.attributeValue("name", "unknown");
            if ("canSeeEvents".equals(right)) {
                return sessionContext.hasPermissionAnyAuthority(Right.Events);
            } else if ("hasRoomAvailability".equals(right)) {
                return RoomAvailability.getInstance() != null;
            } else if ("hasPersonalReport".equals(right)) {
                return sessionContext.isAuthenticated() && PersonalizedExamReportAction
                        .hasPersonalReport(sessionContext.getUser().getExternalUserId());
            } else if ("isChameleon".equals(right)) {
                return sessionContext.isAuthenticated() && (sessionContext.hasPermission(Right.Chameleon)
                        || sessionContext.getUser() instanceof UserContext.Chameleon);
            } else if ("isSectioningEnabled".equals(right)) {
                return solverServerService.isOnlineStudentSchedulingEnabled();
            } else if ("isStudent".equals(right)) {
                return sessionContext.isAuthenticated() && sessionContext.getUser().hasRole(Roles.ROLE_STUDENT);
            } else if ("isInstructor".equals(right)) {
                return sessionContext.isAuthenticated() && sessionContext.getUser().hasRole(Roles.ROLE_INSTRUCTOR);
            } else if ("isRegistrationEnabled".equals(right)) {
                return solverServerService.isStudentRegistrationEnabled();
            } else {
                if ("canSeeCourses".equals(right)) {
                    return sessionContext.hasPermission(Right.InstructionalOfferings)
                            || sessionContext.hasPermission(Right.Classes);
                } else if ("canSeeTimetable".equals(right)) {
                    return sessionContext.hasPermission(Right.ClassAssignments);
                } else if ("canDoTimetable".equals(right)) {
                    return sessionContext.hasPermission(Right.CourseTimetabling);
                } else if ("hasASolverGroup".equals(right)) {
                    return sessionContext.isAuthenticated()
                            && !SolverGroup.getUserSolverGroups(sessionContext.getUser()).isEmpty();
                } else if ("canSectionStudents".equals(right)) {
                    return sessionContext.hasPermission(Right.StudentScheduling);
                } else if ("canSeeExams".equals(right)) {
                    return sessionContext.hasPermission(Right.Examinations);
                } else if ("canTimetableExams".equals(right)) {
                    return sessionContext.hasPermission(Right.ExaminationTimetabling);
                } else if ("canAudit".equals(right)) {
                    return sessionContext.hasPermission(Right.CourseTimetablingAudit);
                } else if ("hasCourseReports".equals(right)) {
                    return sessionContext.hasPermission(Right.HQLReportsCourses)
                            && SavedHQL.hasQueries(SavedHQL.Flag.APPEARANCE_COURSES,
                                    sessionContext.hasPermission(Right.HQLReportsAdminOnly));
                } else if ("hasExamReports".equals(right)) {
                    return sessionContext.hasPermission(Right.HQLReportsExaminations)
                            && SavedHQL.hasQueries(SavedHQL.Flag.APPEARANCE_EXAMS,
                                    sessionContext.hasPermission(Right.HQLReportsAdminOnly));
                } else if ("hasEventReports".equals(right)) {
                    return sessionContext.hasPermission(Right.HQLReportsEvents)
                            && SavedHQL.hasQueries(SavedHQL.Flag.APPEARANCE_EVENTS,
                                    sessionContext.hasPermission(Right.HQLReportsAdminOnly));
                } else if ("hasStudentReports".equals(right)) {
                    return sessionContext.hasPermission(Right.HQLReportsStudents)
                            && SavedHQL.hasQueries(SavedHQL.Flag.APPEARANCE_SECTIONING,
                                    sessionContext.hasPermission(Right.HQLReportsAdminOnly));
                }
            }
            sLog.warn("Unknown right " + right + ".");
            return true;
        }
        sLog.warn("Unknown condition " + cond + ".");
        return true;
    }
}