Subversion Repositories bacoAlunos

Rev

Rev 1314 | Blame | Compare with Previous | Last modification | View Log | RSS feed

package pt.estgp.estgweb.web;

import org.apache.log4j.Logger;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.dom4j.*;
import pt.estgp.estgweb.domain.UserSession;
import pt.estgp.estgweb.services.directories.DirectoryNodeType;
import pt.estgp.estgweb.utils.*;
import pt.estgp.estgweb.utils.Globals;
import pt.estgp.estgweb.web.controllers.ApplicationController;
import pt.estgp.estgweb.web.exceptions.NotAuthorizedException;
import pt.estgp.estgweb.web.utils.RequestUtils;
import pt.utl.ist.berserk.logic.serviceManager.IServiceManager;
import pt.utl.ist.berserk.logic.serviceManager.ServiceManager;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author Jorge Machado
 * @date 26/Fev/2008
 * @time 18:01:54
 * @see pt.estgp.estgweb.web
 */

public class DirLayoutController extends ApplicationController
{

    private static final 1.5.0/docs/api/java/util/logging/Logger.html">Logger logger = 1.5.0/docs/api/java/util/logging/Logger.html">Logger.getLogger(DirLayoutController.class);

    public static Map<String, String> namespaces = new HashMap<String, String>();

    static
    {
        namespaces.put("d", "http://www.estgp.pt/baco/directory/");
    }



    private static class Rights
    {
        List<RightsT> rightsT;
        boolean internal = false; //by default
    }

    private static class RightsT
    {
        1.5.0/docs/api/java/lang/String.html">String text;
        RightsTClass rightsTClass;
        RightsTType type;

        private static enum RightsTType
        {
            permit,
            restrict
        }

        private static enum RightsTClass
        {
            role,
            user
        }
    }

    public ActionForward execute(ActionMapping mapping,
                                 ActionForm form,
                                 HttpServletRequest request,
                                 HttpServletResponse response)
            throws 1.5.0/docs/api/java/io/IOException.html">IOException, ServletException
    {

        /**
         * 1 - Obtain Directory XML
         * 2 - Build a Xpath query based on path
         * 3 - Set Actual Node
         * 4 - Check Actual Node Rights
         * 5 - If is a leaf check absolute just to confirm the request is valid, if absolute redirect just in case
         * 6 - If is a leaf check layout to define the use of a layout and get directory@layout to choose layout to forward in struts
         * 7 - If is a leaf check style to define the use of a style and allays put the object in "body" parameter or directly put content in layout
         * 8 - If is a leaf check proxy to know if it is an proxied source if it is get content by URL concat or just forward to an internal localhost/context/path
         *  8.1 in this case check if is to be layout, usuallly will not be laouted but just in case check it.
         *
         *
         * No WebProxy colocar o contextPath, o user, os Roles, o actual node, username, name, body se for o caso de puxar
         */



        UserSession userSession = UserSessionProxy.loadUserSessionFromRequest(request);


        1.5.0/docs/api/java/lang/String.html">String directory = request.getParameter("directory");
        1.5.0/docs/api/java/lang/String.html">String path = request.getParameter("path");

        try
        {


            IServiceManager sm = ServiceManager.getInstance();
            1.5.0/docs/api/java/lang/String.html">String[] names = new 1.5.0/docs/api/java/lang/String.html">String[]{};
            5+0%2Fdocs%2Fapi+Object">Object[] args = new 5+0%2Fdocs%2Fapi+Object">Object[]{directory};
            5+0%2Fdocs%2Fapi+Document">Document directoryDocument;
            try
            {
                1.5.0/docs/api/java/lang/String.html">String dXml = (1.5.0/docs/api/java/lang/String.html">String) sm.execute(RequestUtils.getRequester(request, response), "LoadDirectoryServiceXml", args, names);
                directoryDocument = Dom4jUtil.parse(dXml);
            }
            catch (1.5.0/docs/api/java/lang/Throwable.html">Throwable e)
            {
                logger.error(e, e);
                throw new 1.5.0/docs/api/java/io/IOException.html">IOException(e.toString());
            }


            if (path.startsWith("/"))
                path = path.substring(1);
            1.5.0/docs/api/java/lang/String.html">String[] ids = path.split("/");

            DirectoryNodeType directoryNodeType = null;
            1.5.0/docs/api/java/lang/String.html">String actualNodeId = null;
            5+0%2Fdocs%2Fapi+Element">Element actualNode = null;
            int stopName = 0;
            //vai ficar com o ultimo nó nao externo lido no ciclo
            List<Rights> rights = new ArrayList<Rights>();
            for (1.5.0/docs/api/java/lang/String.html">String id : ids)
            {
                1.5.0/docs/api/javax/xml/xpath/XPath.html">XPath idXpath = directoryDocument.createXPath("//*[@id='" + id + "']");

                idXpath.setNamespaceURIs(namespaces);
                5+0%2Fdocs%2Fapi+Element">Element idElem = (5+0%2Fdocs%2Fapi+Element">Element) idXpath.selectSingleNode(directoryDocument);
                if (idElem == null)
                {
                    directoryNodeType = DirectoryNodeType.external;
                    break;
                }
                Rights r = buildRights(idElem, namespaces);
                if (r != null)
                    rights.add(r);
                1.5.0/docs/api/java/lang/String.html">String name = idElem.getQName().getName();
                boolean node = 1.5.0/docs/api/java/lang/Boolean.html">Boolean.parseBoolean(idElem.attributeValue("node"));
                if (name.equals("leaf") && !node)
                {
                    directoryNodeType = DirectoryNodeType.leaf;
                    actualNodeId = id;
                    actualNode = idElem;
                }
                else if (name.equals("leaf") && node)
                {
                    directoryNodeType = DirectoryNodeType.node;
                    actualNodeId = id;
                    actualNode = idElem;
                }
                else if (name.equals("directory"))
                {
                    directoryNodeType = DirectoryNodeType.directory;
                    actualNodeId = id;
                    actualNode = idElem;
                }
                else
                {
                    logger.error("Unexpected node " + name + " with id " + id);
                    return mapping.findForward("500");
                }
                stopName++;
            }
            if (directoryNodeType == null)
            {
                logger.error("Unexpected, no nodes found for given id path " + path + " in directory " + directory);
                return mapping.findForward("500");
            }
            else
            {
                if (!checkRights(rights, userSession))
                    throw new NotAuthorizedException("user: " + userSession.getUsername() + " trying access node " + actualNodeId + " in directory " + directory);
                if (!pruneDocument(directoryDocument.getRootElement(), namespaces, userSession))
                {
                    throw new NotAuthorizedException("user: " + userSession.getUsername() + " trying access directory: " + directory);
                }
                1.5.0/docs/api/java/lang/String.html">String externalFile = buildExternalFile(stopName, ids);

                putInRequestCommonAttributes(request,actualNode, actualNodeId, directoryDocument);

                5+0%2Fdocs%2Fapi+Attribute">Attribute layoutStrAtt = directoryDocument.getRootElement().attribute("layout");
                5+0%2Fdocs%2Fapi+Attribute">Attribute layoutRootStrAtt = directoryDocument.getRootElement().attribute("layoutRoot");
                1.5.0/docs/api/java/lang/String.html">String layoutChoosed = (layoutStrAtt != null ? layoutStrAtt.getValue() : "layoutEmpty");
                1.5.0/docs/api/java/lang/String.html">String rootLayoutChoosed = (layoutRootStrAtt != null ? layoutRootStrAtt.getValue() : "layout1");

                if (directoryNodeType == DirectoryNodeType.node)
                {
                    request.setAttribute("element", "node");
                    return mapping.findForward(layoutChoosed);
                }
                else if (directoryNodeType == DirectoryNodeType.directory)
                {
                    request.setAttribute("element", "node");
                    return mapping.findForward(rootLayoutChoosed);
                }
                else if (directoryNodeType == DirectoryNodeType.leaf || directoryNodeType == DirectoryNodeType.external)
                {
                    request.setAttribute("element", "leaf");

                    1.5.0/docs/api/java/lang/String.html">String url = getAttributeValue(actualNode, "url");
                    1.5.0/docs/api/java/lang/String.html">String label = getAttributeValue(actualNode, "label");
                    1.5.0/docs/api/java/lang/String.html">String xml = getAttributeValue(actualNode, "xml");
                    1.5.0/docs/api/java/lang/String.html">String layout = getAttributeValue(actualNode, "layout");
                    1.5.0/docs/api/java/lang/String.html">String style = getAttributeValue(actualNode, "style");
                    1.5.0/docs/api/java/lang/String.html">String absolute = getAttributeValue(actualNode, "absolute");
                    1.5.0/docs/api/java/lang/String.html">String proxy = getAttributeValue(actualNode, "proxy");

                    if(style == null)
                        style = "true";

                    //Confirm just in case
                    if (url != null && absolute != null && absolute.equals("true"))
                        return redirect(response, url);
                    else
                    {
                        boolean layoutDo = true;
                        if (layout != null && layout.length() > 0) layoutDo = 1.5.0/docs/api/java/lang/Boolean.html">Boolean.parseBoolean(layout);
                        if (!layoutDo) layoutChoosed = "layoutEmpty";
                        putProxyAttributes(request, proxy, externalFile,xml,url);
                        FtpManager.checkIfAnyFilesToUploadFromRequest(this, request, response);
                        request.setAttribute("label", label);
                        request.setAttribute("style", style);
                        request.setAttribute("xml", xml);
                        if(style.equals("false") && !layoutDo)
                            request.setAttribute("useOutputStream", "true");
                        if(request.getAttribute("useOutputStream") != null && request.getAttribute("useOutputStream").equals("true"))
                        {
                            ActionForward forward = new ActionForward();
                            forward.setPath("/DirWebProxy");
                            return forward;
                        }
                        else
                        {
                            return mapping.findForward(layoutChoosed);
                        }
                    }
                }
            }
        }
        catch (1.5.0/docs/api/java/lang/Throwable.html">Throwable e) {
            logger.error(e, e);
            throw new 1.5.0/docs/api/java/io/IOException.html">IOException(e.toString());
        }
        ActionForward forward = new ActionForward();
        request.setAttribute("useOutputStream", "true");
        forward.setPath("/WebProxy");
        return forward;
    }

    private 1.5.0/docs/api/java/lang/String.html">String getAttributeValue(5+0%2Fdocs%2Fapi+Element">Element actualNode, 1.5.0/docs/api/java/lang/String.html">String name)
    {
        return (actualNode.attribute(name) != null ? actualNode.attribute(name).getValue() : null);
    }

    private void putProxyAttributes(HttpServletRequest request, 1.5.0/docs/api/java/lang/String.html">String proxy, 1.5.0/docs/api/java/lang/String.html">String externalFile, 1.5.0/docs/api/java/lang/String.html">String xml, 1.5.0/docs/api/java/lang/String.html">String url)
    {

        1.5.0/docs/api/java/lang/String.html">String server = ConfigProperties.getProperty("server." + proxy);
        1.5.0/docs/api/java/lang/String.html">String proxyHost = ConfigProperties.getProperty(proxy + ".proxy.host");
        1.5.0/docs/api/java/lang/String.html">String proxyPort = ConfigProperties.getProperty(proxy + ".proxy.port");
        1.5.0/docs/api/java/lang/String.html">String confStartPath = ConfigProperties.getProperty("server." + proxy + ".start.path");


        request.setAttribute("leaf.url", url);
        request.setAttribute("server", server);
        request.setAttribute("proxyKey", proxy);
        request.setAttribute("proxy.host", proxyHost);
        request.setAttribute("proxy.port", proxyPort);
        if (confStartPath != null)
            externalFile = confStartPath + externalFile;
        request.setAttribute("path", externalFile);
        request.setAttribute("startPath", confStartPath);


        if(confStartPath == null)
            confStartPath = "";
        if(externalFile == null)
            externalFile = "";
        boolean isLeafButBringsNoExternalPathAfterPathInXml = confStartPath.equals(externalFile);
        if(isLeafButBringsNoExternalPathAfterPathInXml || (xml != null && xml.equals("true")))
        {
            1.5.0/docs/api/java/lang/String.html">String encoding = ConfigProperties.getProperty(proxy + ".encoding");
            request.setAttribute("encoding", encoding);
            request.setAttribute("useOutputStream", "false");
            return;
        }
        for(1.5.0/docs/api/java/lang/String.html">String extension: pt.estgp.estgweb.utils.Globals.PROXY_EXTENSIONS)
        {
            if(externalFile.endsWith("." + extension))
            {
                1.5.0/docs/api/java/lang/String.html">String encoding = ConfigProperties.getProperty(proxy + ".encoding");
                request.setAttribute("encoding", encoding);
                request.setAttribute("useOutputStream", "false");
                return;
            }
        }
        if(!server.startsWith("ftp://"))
            request.setAttribute("useOutputStream", "true");
    }

    private void putInRequestCommonAttributes(HttpServletRequest request,5+0%2Fdocs%2Fapi+Element">Element actualNode, 1.5.0/docs/api/java/lang/String.html">String actualNameId, 5+0%2Fdocs%2Fapi+Document">Document directoryDocument)
    {
        /**
         * Attributes used in Nodes and Leafs
         */


        5+0%2Fdocs%2Fapi+Attribute">Attribute targetRoleStrAtt = directoryDocument.getRootElement().attribute("targetRole");
        5+0%2Fdocs%2Fapi+Attribute">Attribute styleStrAtt = directoryDocument.getRootElement().attribute("style");

        1.5.0/docs/api/java/lang/String.html">String targetRoleChoosed = (targetRoleStrAtt != null ? targetRoleStrAtt.getValue() : Globals.ALL_ROLE);
        1.5.0/docs/api/java/lang/String.html">String styleChoosed = (styleStrAtt != null ? styleStrAtt.getValue() : "style1.xsl");

        /**
         * Prepare request to forward to Layout Tile
         */

        request.setAttribute("stylesheet", "/pt/estgp/estgweb/directories/" + styleChoosed);
        request.setAttribute("directoryDocument", directoryDocument);
        request.setAttribute("actualNodeId", actualNameId);
        request.setAttribute("actualNode", actualNode);
        request.setAttribute("targetRole", targetRoleChoosed);
    }

    private ActionForward redirect(HttpServletResponse response, 1.5.0/docs/api/java/lang/String.html">String url) throws 1.5.0/docs/api/java/io/IOException.html">IOException
    {
        response.sendRedirect(url);
        ActionForward forward = new ActionForward();
        forward.setRedirect(true);
        forward.setPath(url);
        return forward;
    }

    /**
     * Creates the name of the file in the link considering the last ID in url
     *
     * example for /student/servicosOnLine/servSecretaria/public/portal/servicosSecretaria.html
     * in directory student
     * external name will be
     * /public/portal/servicosSecretaria.html
     * because there are nodes in directory with id student, servicosOnLine and servSecretaria
     *
     * example if url = /student/servicosOnLine/servSecretaria/
     * externalFile will be "" with len = 0 URL must be obtained from LEAF
     * Verificado este caso em que stopName = ultimo ID
     * No DirWebProxy a primeira coisa que é feita se o path = confStartPath é concatenar
     * o leaf URL caso contrario o LEAF URL é ignorado
     * @param stopName first id not in directory tree
     * @param ids list of words separated by / in url
     * @return external file url path
     */

    private 1.5.0/docs/api/java/lang/String.html">String buildExternalFile(int stopName, 1.5.0/docs/api/java/lang/String.html">String[] ids)
    {

        if (stopName <= ids.length)
        {
            1.5.0/docs/api/java/lang/StringBuilder.html">StringBuilder externalFileBuilder = new 1.5.0/docs/api/java/lang/StringBuilder.html">StringBuilder();
            for (int i = stopName; i < ids.length; i++)
            {
                int questionMark = ids[i].indexOf("?");
                if (questionMark >= 0)
                {
                    externalFileBuilder.append("/").append(ids[i].substring(0, questionMark));
                    break;
                }
                else
                    externalFileBuilder.append("/").append(ids[i]);
            }
            return externalFileBuilder.toString();
        }
        return null;
    }

    public static Namespace dirNamespace = new Namespace("d", "http://www.estgp.pt/baco/directory/");
    //public static QName nodeDir = new QName("node", dirNamespace);
    //public static QName leafDir = new QName("leaf", dirNamespace);

    private boolean pruneDocument(5+0%2Fdocs%2Fapi+Element">Element startElem, 1.5.0/docs/api/java/util/Map.html">Map namespaces, UserSession userSession)
    {
        Rights rights = buildRights(startElem, namespaces);
        if (rights != null && !checkRights(rights, userSession))
        {
            5+0%2Fdocs%2Fapi+Element">Element parentNode = startElem.getParent();
            if (parentNode != null)
                parentNode.remove(startElem);
            return false;
        }
        1.5.0/docs/api/javax/xml/xpath/XPath.html">XPath leafXpath = startElem.createXPath("./d:leaf[@node='false']");
        1.5.0/docs/api/javax/xml/xpath/XPath.html">XPath nodeXpath = startElem.createXPath("./d:leaf[@node='true']");
        leafXpath.setNamespaceURIs(namespaces);
        nodeXpath.setNamespaceURIs(namespaces);
        List<Element> nodes = nodeXpath.selectNodes(startElem);
        List<Element> leafs = leafXpath.selectNodes(startElem);
        for (5+0%2Fdocs%2Fapi+Element">Element childNode : nodes)
        {
            pruneDocument(childNode, namespaces, userSession);
        }
        for (5+0%2Fdocs%2Fapi+Element">Element childLeaf : leafs)
        {
            pruneDocument(childLeaf, namespaces, userSession);
        }
        return true;
    }

    private Rights buildRights(5+0%2Fdocs%2Fapi+Element">Element nodeOrLeaf, 1.5.0/docs/api/java/util/Map.html">Map namespaces)
    {
        1.5.0/docs/api/javax/xml/xpath/XPath.html">XPath rightsXpath = nodeOrLeaf.createXPath("./d:rights");
        rightsXpath.setNamespaceURIs(namespaces);
        5+0%2Fdocs%2Fapi+Element">Element rightsElem = (5+0%2Fdocs%2Fapi+Element">Element) rightsXpath.selectSingleNode(nodeOrLeaf);
        if (rightsElem == null)
            return null;
        else
        {
            Rights rights = new Rights();

            1.5.0/docs/api/javax/xml/xpath/XPath.html">XPath userXpath = rightsElem.createXPath("./d:right[@target='user']");
            userXpath.setNamespaceURIs(namespaces);
            List<Element> userElems = userXpath.selectNodes(rightsElem);

            1.5.0/docs/api/javax/xml/xpath/XPath.html">XPath roleXpath = rightsElem.createXPath("./d:right[@target='role']");
            roleXpath.setNamespaceURIs(namespaces);
            List<Element> rolesElems = roleXpath.selectNodes(rightsElem);

            1.5.0/docs/api/javax/xml/xpath/XPath.html">XPath internalXpath = rightsElem.createXPath("./d:internal");
            internalXpath.setNamespaceURIs(namespaces);
            5+0%2Fdocs%2Fapi+Element">Element internalElem = (5+0%2Fdocs%2Fapi+Element">Element) internalXpath.selectSingleNode(rightsElem);


            rights.rightsT = new ArrayList<RightsT>();

            if (userElems != null && userElems.size() > 0)
            {
                for (5+0%2Fdocs%2Fapi+Element">Element userElem : userElems)
                {
                    RightsT rightsT = new RightsT();
                    rightsT.rightsTClass = RightsT.RightsTClass.user;
                    rightsT.text = userElem.attribute("name").getText();
                    1.5.0/docs/api/java/lang/String.html">String type = userElem.attribute("type").getText();
                    if (type.equals("permit"))
                        rightsT.type = RightsT.RightsTType.permit;
                    else
                        rightsT.type = RightsT.RightsTType.restrict;
                    rights.rightsT.add(rightsT);
                }
            }

            if (rolesElems != null && rolesElems.size() > 0)
            {
                for (5+0%2Fdocs%2Fapi+Element">Element roleElem : rolesElems)
                {
                    RightsT rightsT = new RightsT();
                    rightsT.rightsTClass = RightsT.RightsTClass.role;
                    rightsT.text = roleElem.attribute("name").getText();
                    1.5.0/docs/api/java/lang/String.html">String type = roleElem.attribute("type").getText();
                    if (type.equals("permit"))
                        rightsT.type = RightsT.RightsTType.permit;
                    else
                        rightsT.type = RightsT.RightsTType.restrict;
                    rights.rightsT.add(rightsT);
                }
            }

            if (internalElem != null)
            {
                if (internalElem.getText() != null && internalElem.getText().trim().equals("true"))
                    rights.internal = true;
            }
            return rights;
        }
    }

    private boolean checkRights(List<Rights> rights, UserSession userSession)
    {
        if (rights != null && rights.size() > 0)
        {
            for (Rights r : rights)
            {
                if (!checkRights(r, userSession))
                    return false;
            }
            return true;
        }
        return true;
    }

    /**
     * Check if a user can access through a Rights Element
     *
     * @param r
     * @param userSession
     * @return
     */

    private boolean checkRights(Rights r, UserSession userSession)
    {
        if (r.internal && userSession.getUser() == null)
            return false;
        else
        {
            if (r.rightsT != null && r.rightsT.size() > 0)
            {
                boolean ok = true;
                boolean permitActivated = false;
                for (RightsT rightsT : r.rightsT)
                {
                    if (permitActivated && rightsT.type == RightsT.RightsTType.restrict)
                    {
                        //do nothing
                    }
                    else
                    {
                        if (rightsT.type == RightsT.RightsTType.restrict) //implicitly permitActivated = false
                        {
                            if (rightsT.rightsTClass == RightsT.RightsTClass.user && userSession.getUsername() != null && userSession.getUsername().equals(rightsT.text))
                                return false;
                            else
                            if (rightsT.rightsTClass == RightsT.RightsTClass.role && userSession.getUsername() != null && userSession.getUser() != null && userSession.getUser().hasRole(rightsT.text))
                                return false;
                        }
                        else
                        {
                            //One permit mean that just if specific permission was given it will let him pass
                            permitActivated = true;
                            ok = false;
                            if (rightsT.rightsTClass == RightsT.RightsTClass.user && userSession.getUsername() != null && userSession.getUsername().equals(rightsT.text))
                            {
                                ok = true;
                                break;
                            }
                            else
                            if (rightsT.rightsTClass == RightsT.RightsTClass.role && userSession.getUsername() != null && userSession.getUser().hasRole(rightsT.text))
                            {
                                ok = true;
                                break;
                            }
                        }
                    }
                }
                if (!ok)
                    return false;
            }
        }
        return true;
    }




}