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.ConfigProperties;
import pt.estgp.estgweb.utils.Dom4jUtil;
import pt.estgp.estgweb.web.controllers.ApplicationDispatchController;
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 ApplicationDispatchController
{
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;
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.
checkOperations(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.
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() : pt.
estgp.
estgweb.
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
;
}
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;
}
}