/**
* Copyright (C) 2010 eXo Platform SAS.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*
*/
package org.exoplatform.services.jcr.webdav.command.acl;
import org.exoplatform.common.util.HierarchicalProperty;
import org.exoplatform.services.jcr.access.AccessControlEntry;
import org.exoplatform.services.jcr.access.AccessControlList;
import org.exoplatform.services.jcr.access.PermissionType;
import org.exoplatform.services.jcr.impl.core.NodeImpl;
import org.exoplatform.services.jcr.webdav.util.PropertyConstants;
import org.exoplatform.services.security.IdentityConstants;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import javax.jcr.RepositoryException;
import javax.xml.namespace.QName;
/**
* Created by The eXo Platform SAS.
* Utility class to simplify operations with ACL properties of JCR nodes
* for PROPFIND method.
*
* @author Vitaliy Gulyy - gavrikvetal@gmail.com
* @version $
*/
public class ACLProperties
{
/**
* Defines the name of the element corresponding to a protected property that specifies
* the list of access control entries.
* More details can be found <a href="http://www.webdav.org/specs/rfc3744.html#PROPERTY_acl">here</a>.
*/
public final static QName ACL = new QName("DAV:", "acl");
/**
* Defines the name of the element corresponding to a property that the set of privileges
* to be either granted or denied to a single principal.
* More details can be found <a href="http://www.webdav.org/specs/rfc3744.html#PROPERTY_acl">here</a>.
*/
public final static QName ACE = new QName("DAV:", "ace");
/**
* Defines the name of the element corresponding to a property which identifies the principal
* to which this ACE applies.
* More details can be found <a href='http://www.webdav.org/specs/rfc3744.html#principals'>here</a>
* and <a href="http://www.webdav.org/specs/rfc3744.html#PROPERTY_acl">here</a>.
*/
public final static QName PRINCIPAL = new QName("DAV:", "principal");
/**
* Defines the name of the element corresponding to a property that can be either an aggregate
* privilege that contains the entire set of privileges that can be applied to the resource or
* an aggregate principal that contains the entire set of principals.
* More details can be found <a href="http://www.webdav.org/specs/rfc3744.html#PRIVILEGE_all">here</a>.
*/
public final static QName ALL = new QName("DAV:", "all");
/**
* Defines the name of the element corresponding to a property which is used to uniquely
* identify a principal.
* More details can be found <a href="http://www.webdav.org/specs/rfc3744.html#PROPERTY_principal-URL">here</a>.
*/
public final static QName HREF = new QName("DAV:", "href");
/**
* Defines the name of the element containing privilege's name.
* More details can be found <a href="http://www.webdav.org/specs/rfc3744.html#privileges">here</a>.
*/
public final static QName PRIVILEGE = new QName("DAV:", "privilege");
/**
* Defines the name of the element containing privileges to be granted.
* More details can be found <a href="http://www.webdav.org/specs/rfc3744.html#rfc.section.5.5.2">here</a>.
*/
public final static QName GRANT = new QName("DAV:", "grant");
/**
* Defines the name of the element containing privileges to be denied.
* More details can be found <a href="http://www.webdav.org/specs/rfc3744.html#rfc.section.5.5.2">here</a>.
*/
public final static QName DENY = new QName("DAV:", "deny");
/**
* Defines the name of the element corresponding to write privilege
* which in current implementation aggregate:
* ADD_NODE, SET_PROPERTY, REMOVE permissions.
* More details can be found <a href="http://www.webdav.org/specs/rfc3744.html#privileges">here</a>.
*/
public final static QName WRITE = new QName("DAV:", "write");
/**
* Defines the name of the element corresponding to read privilege
* which in current implementation aggregate:
* READ permission.
* More details can be found <a href="http://www.webdav.org/specs/rfc3744.html#privileges">here</a>.
*/
public final static QName READ = new QName("DAV:", "read");
/**
* Gets {@link AccessControlList} and transform it to DAV:acl property view
* represented by a {@link HierarchicalProperty} instance.
* @param node - {@link NodeImpl} from which we are to get an ACL
* @return HierarchicalProperty - tree like structure corresponding to an DAV:acl property
* @throws RepositoryException
*/
public static HierarchicalProperty getACL(NodeImpl node) throws RepositoryException
{
HierarchicalProperty property = new HierarchicalProperty(ACL);
AccessControlList acl = node.getACL();
HashMap<String, List<String>> principals = new HashMap<String, List<String>>();
List<AccessControlEntry> entryList = acl.getPermissionEntries();
for (AccessControlEntry entry : entryList)
{
String principal = entry.getIdentity();
String grant = entry.getPermission();
List<String> grantList = principals.get(principal);
if (grantList == null)
{
grantList = new ArrayList<String>();
principals.put(principal, grantList);
}
grantList.add(grant);
}
Iterator<String> principalIter = principals.keySet().iterator();
while (principalIter.hasNext())
{
HierarchicalProperty aceProperty = new HierarchicalProperty(ACE);
String curPrincipal = principalIter.next();
aceProperty.addChild(getPrincipalProperty(curPrincipal));
aceProperty.addChild(getGrantProperty(principals.get(curPrincipal)));
property.addChild(aceProperty);
}
return property;
}
/**
* Transform owner got from node's {@link AccessControlList}
* to tree like {@link HierarchicalProperty} instance to use in PROPFIND response body
* @param node
* @return {@link HierarchicalProperty} representation of node owner
* @throws RepositoryException
*/
public static HierarchicalProperty getOwner(NodeImpl node) throws RepositoryException
{
HierarchicalProperty ownerProperty = new HierarchicalProperty(PropertyConstants.OWNER);
HierarchicalProperty href = new HierarchicalProperty(new QName("DAV:", "href"));
href.setValue(node.getACL().getOwner());
ownerProperty.addChild(href);
return ownerProperty;
}
private static HierarchicalProperty getPrincipalProperty(String principal)
{
HierarchicalProperty principalProperty = new HierarchicalProperty(PRINCIPAL);
if (IdentityConstants.ANY.equals(principal))
{
HierarchicalProperty all = new HierarchicalProperty(ALL);
principalProperty.addChild(all);
}
else
{
HierarchicalProperty href = new HierarchicalProperty(HREF);
href.setValue(principal);
principalProperty.addChild(href);
}
return principalProperty;
}
private static HierarchicalProperty getGrantProperty(List<String> grantList)
{
HierarchicalProperty grant = new HierarchicalProperty(GRANT);
if (grantList.contains(PermissionType.ADD_NODE) || grantList.contains(PermissionType.SET_PROPERTY)
|| grantList.contains(PermissionType.REMOVE))
{
HierarchicalProperty privilege = new HierarchicalProperty(PRIVILEGE);
privilege.addChild(new HierarchicalProperty(WRITE));
grant.addChild(privilege);
}
if (grantList.contains(PermissionType.READ))
{
HierarchicalProperty privilege = new HierarchicalProperty(PRIVILEGE);
privilege.addChild(new HierarchicalProperty(READ));
grant.addChild(privilege);
}
return grant;
}
}