Java tutorial
/* * This program is free software; you can redistribute it and/or modify it under the * terms of the GNU General Public License, version 2 as published by the Free Software * Foundation. * * You should have received a copy of the GNU General Public License along with this * program; if not, you can obtain a copy at http://www.gnu.org/licenses/gpl-2.0.html * or from the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * 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. * * * Copyright 2006 - 2013 Pentaho Corporation. All rights reserved. */ package org.pentaho.platform.repository2.unified.jcr; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.jackrabbit.api.security.user.Group; import org.pentaho.platform.api.repository2.unified.RepositoryFile; import org.pentaho.platform.api.repository2.unified.RepositoryFileAce; import org.pentaho.platform.api.repository2.unified.RepositoryFileAcl; import org.pentaho.platform.api.repository2.unified.RepositoryFilePermission; import org.pentaho.platform.api.repository2.unified.RepositoryFileSid; import org.pentaho.platform.repository2.messages.Messages; import org.pentaho.platform.repository2.unified.jcr.IAclMetadataStrategy.AclMetadata; import org.pentaho.platform.repository2.unified.jcr.JcrRepositoryFileAclDao.IPermissionConversionHelper; import org.pentaho.platform.repository2.unified.jcr.jackrabbit.security.SpringSecurityRolePrincipal; import org.pentaho.platform.repository2.unified.jcr.jackrabbit.security.SpringSecurityUserPrincipal; import javax.jcr.ItemNotFoundException; import javax.jcr.Node; import javax.jcr.RepositoryException; import javax.jcr.Session; import javax.jcr.security.AccessControlEntry; import javax.jcr.security.AccessControlList; import javax.jcr.security.AccessControlManager; import javax.jcr.security.AccessControlPolicy; import javax.jcr.security.AccessControlPolicyIterator; import javax.jcr.security.Privilege; import java.io.Serializable; import java.lang.reflect.Constructor; import java.security.Principal; import java.util.Arrays; import java.util.EnumSet; import java.util.HashSet; import java.util.List; import java.util.Set; /** * ACL utilities. * * <p> * These utility methods are static because they are used from within Jackrabbit. * </p> * * @author mlowery */ public class JcrRepositoryFileAclUtils { // ~ Static fields/initializers // ====================================================================================== private static final Log logger = LogFactory.getLog(JcrRepositoryFileAclUtils.class); public static final String DEFAULT = "DEFAULT"; //$NON-NLS-1$ public static final String SYSTEM_PROPERTY = "pentaho.repository.server.aclMetadataStrategy"; //$NON-NLS-1$ private static String strategyName = System.getProperty(SYSTEM_PROPERTY); private static IAclMetadataStrategy strategy; static { initialize(); } // ~ Instance fields // ================================================================================================= // ~ Constructors // ==================================================================================================== private JcrRepositoryFileAclUtils() { super(); } // ~ Methods // ========================================================================================================= private static void initialize() { if ((strategyName == null) || "".equals(strategyName)) { //$NON-NLS-1$ strategyName = DEFAULT; } if (strategyName.equals(DEFAULT)) { strategy = new JcrAclMetadataStrategy(); } else { // Try to load a custom strategy try { Class<?> clazz = Class.forName(strategyName); Constructor<?> customStrategy = clazz.getConstructor(new Class[] {}); strategy = (IAclMetadataStrategy) customStrategy.newInstance(new Object[] {}); } catch (Exception e) { throw new RuntimeException(e); } } logger.debug("JcrRepositoryFileAclUtils initialized: strategy=" + strategyName); //$NON-NLS-1$ } public static AclMetadata getAclMetadata(final Session session, final String path, final AccessControlList acList) throws RepositoryException { return strategy.getAclMetadata(session, path, acList); } public static void setAclMetadata(final Session session, final String path, final AccessControlList acList, final AclMetadata aclMetadata) throws RepositoryException { strategy.setAclMetadata(session, path, acList, aclMetadata); } public static List<AccessControlEntry> removeAclMetadata(final List<AccessControlEntry> acEntries) throws RepositoryException { return strategy.removeAclMetadata(acEntries); } /** * Expands all aggregate privileges. * * @param privileges * input privileges * @param expandNonStandardOnly * if {@code true} expand only privileges outside of jcr: namespace * @return expanded privileges */ public static Privilege[] expandPrivileges(final Privilege[] privileges, final boolean expandNonStandardOnly) { // find all aggregate privileges and expand Set<Privilege> expandedPrivileges = new HashSet<Privilege>(); expandedPrivileges.addAll(Arrays.asList(privileges)); while (true) { boolean foundAggregatePrivilege = false; Set<Privilege> iterable = new HashSet<Privilege>(expandedPrivileges); for (Privilege privilege : iterable) { // expand impl custom privileges (e.g. rep:write) but keep aggregates like jcr:write intact if (!expandNonStandardOnly || expandNonStandardOnly && !privilege.getName().startsWith("jcr:")) { //$NON-NLS-1$ if (privilege.isAggregate()) { expandedPrivileges.remove(privilege); expandedPrivileges.addAll(Arrays.asList(privilege.getAggregatePrivileges())); foundAggregatePrivilege = true; } } } if (!foundAggregatePrivilege) { break; } } return expandedPrivileges.toArray(new Privilege[0]); } public static RepositoryFileAcl createAcl(Session session, PentahoJcrConstants pentahoJcrConstants, Serializable fileId, RepositoryFileAcl acl) throws ItemNotFoundException, RepositoryException { Node node = session.getNodeByIdentifier(fileId.toString()); String absPath = node.getPath(); AccessControlManager acMgr = session.getAccessControlManager(); AccessControlList acList = getAccessControlList(acMgr, absPath); acMgr.setPolicy(absPath, acList); return internalUpdateAcl(session, pentahoJcrConstants, fileId, acl); } public static void addPermission(final Session session, final PentahoJcrConstants pentahoJcrConstants, final Serializable fileId, final RepositoryFileSid recipient, final EnumSet<RepositoryFilePermission> permissions) throws RepositoryException { addAce(session, pentahoJcrConstants, fileId, recipient, permissions); } public static void setOwner(final Session session, final PentahoJcrConstants pentahoJcrConstants, final RepositoryFile file, final RepositoryFileSid owner) throws RepositoryException { RepositoryFileSid newOwnerSid = owner; if (JcrTenantUtils.getUserNameUtils().getTenant(owner.getName()) == null) { newOwnerSid = new RepositoryFileSid(JcrTenantUtils.getTenantedUser(owner.getName()), owner.getType()); } RepositoryFileAcl acl = getAcl(session, pentahoJcrConstants, file.getId()); RepositoryFileAcl newAcl = new RepositoryFileAcl.Builder(acl).owner(newOwnerSid).build(); updateAcl(session, newAcl); } public static void setFullControl(final Session session, final PentahoJcrConstants pentahoJcrConstants, final Serializable fileId, final RepositoryFileSid sid) throws RepositoryException { addAce(session, pentahoJcrConstants, fileId, sid, EnumSet.of(RepositoryFilePermission.ALL)); } public static void addAce(final Session session, final PentahoJcrConstants pentahoJcrConstants, final Serializable id, final RepositoryFileSid recipient, final EnumSet<RepositoryFilePermission> permission) throws RepositoryException { RepositoryFileSid newRecipient = recipient; if (JcrTenantUtils.getUserNameUtils().getTenant(recipient.getName()) == null) { newRecipient = new RepositoryFileSid(JcrTenantUtils.getTenantedUser(recipient.getName()), recipient.getType()); } RepositoryFileAcl acl = getAcl(session, pentahoJcrConstants, id); RepositoryFileAcl updatedAcl = new RepositoryFileAcl.Builder(acl).ace(newRecipient, permission).build(); updateAcl(session, updatedAcl); } private static RepositoryFileAcl internalUpdateAcl(final Session session, final PentahoJcrConstants pentahoJcrConstants, final Serializable fileId, final RepositoryFileAcl acl) throws RepositoryException { Node node = session.getNodeByIdentifier(fileId.toString()); if (node == null) { throw new RepositoryException("Node not found"); //$NON-NLS-1$ } String absPath = node.getPath(); AccessControlManager acMgr = session.getAccessControlManager(); AccessControlList acList = getAccessControlList(acMgr, absPath); // clear all entries AccessControlEntry[] acEntries = acList.getAccessControlEntries(); for (int i = 0; i < acEntries.length; i++) { acList.removeAccessControlEntry(acEntries[i]); } JcrRepositoryFileAclUtils.setAclMetadata(session, absPath, acList, new AclMetadata(acl.getOwner().getName(), acl.isEntriesInheriting())); // add entries to now empty list but only if not inheriting; force user to start with clean slate if (!acl.isEntriesInheriting()) { for (RepositoryFileAce ace : acl.getAces()) { Principal principal = null; if (RepositoryFileSid.Type.ROLE == ace.getSid().getType()) { principal = new SpringSecurityRolePrincipal( JcrTenantUtils.getTenantedRole(ace.getSid().getName())); } else { principal = new SpringSecurityUserPrincipal( JcrTenantUtils.getTenantedUser(ace.getSid().getName())); } IPermissionConversionHelper permissionConversionHelper = new DefaultPermissionConversionHelper( session); acList.addAccessControlEntry(principal, permissionConversionHelper.pentahoPermissionsToPrivileges(session, ace.getPermissions())); } } acMgr.setPolicy(absPath, acList); session.save(); return getAcl(session, pentahoJcrConstants, fileId); } public static void updateAcl(final Session session, final RepositoryFileAcl acl) throws RepositoryException { PentahoJcrConstants pentahoJcrConstants = new PentahoJcrConstants(session); JcrRepositoryFileUtils.checkoutNearestVersionableFileIfNecessary(session, pentahoJcrConstants, acl.getId()); internalUpdateAcl(session, pentahoJcrConstants, acl.getId(), acl); JcrRepositoryFileUtils.checkinNearestVersionableFileIfNecessary(session, pentahoJcrConstants, acl.getId(), null, null, true); } public static RepositoryFileAcl getAcl(final Session session, final PentahoJcrConstants pentahoJcrConstants, final Serializable id) throws RepositoryException { Node node = session.getNodeByIdentifier(id.toString()); if (node == null) { throw new RepositoryException(Messages.getInstance() .getString("JackrabbitRepositoryFileAclDao.ERROR_0001_NODE_NOT_FOUND", id.toString())); //$NON-NLS-1$ } String absPath = node.getPath(); AccessControlManager acMgr = session.getAccessControlManager(); AccessControlList acList = getAccessControlList(acMgr, absPath); RepositoryFileSid owner = null; String ownerString = JcrTenantUtils.getUserNameUtils().getPrincipleName(getOwner(session, absPath, acList)); if (ownerString != null) { // for now, just assume all owners are users; only has UI impact owner = new RepositoryFileSid(ownerString, RepositoryFileSid.Type.USER); } RepositoryFileAcl.Builder aclBuilder = new RepositoryFileAcl.Builder(id, owner); aclBuilder.entriesInheriting(isEntriesInheriting(session, absPath, acList)); List<AccessControlEntry> cleanedAcEntries = JcrRepositoryFileAclUtils .removeAclMetadata(Arrays.asList(acList.getAccessControlEntries())); for (AccessControlEntry acEntry : cleanedAcEntries) { aclBuilder.ace(toAce(session, acEntry)); } return aclBuilder.build(); } private static AccessControlList getAccessControlList(final AccessControlManager acMgr, final String path) throws RepositoryException { AccessControlPolicyIterator applicablePolicies = acMgr.getApplicablePolicies(path); while (applicablePolicies.hasNext()) { AccessControlPolicy policy = applicablePolicies.nextAccessControlPolicy(); if (policy instanceof AccessControlList) { return (AccessControlList) policy; } } AccessControlPolicy[] policies = acMgr.getPolicies(path); for (int i = 0; i < policies.length; i++) { if (policies[i] instanceof AccessControlList) { return (AccessControlList) policies[i]; } } throw new IllegalStateException("no access control list applies or is bound to node"); } private static String getOwner(final Session session, final String path, final AccessControlList acList) throws RepositoryException { AclMetadata aclMetadata = JcrRepositoryFileAclUtils.getAclMetadata(session, path, acList); if (aclMetadata != null) { return aclMetadata.getOwner(); } else { return null; } } private static boolean isEntriesInheriting(final Session session, final String path, final AccessControlList acList) throws RepositoryException { AclMetadata aclMetadata = JcrRepositoryFileAclUtils.getAclMetadata(session, path, acList); if (aclMetadata != null) { return aclMetadata.isEntriesInheriting(); } else { return false; } } private static RepositoryFileAce toAce(final Session session, final AccessControlEntry acEntry) throws RepositoryException { Principal principal = acEntry.getPrincipal(); RepositoryFileSid sid = null; if (principal instanceof Group) { sid = new RepositoryFileSid(principal.getName(), RepositoryFileSid.Type.ROLE); } else { sid = new RepositoryFileSid(principal.getName(), RepositoryFileSid.Type.USER); } Privilege[] privileges = acEntry.getPrivileges(); IPermissionConversionHelper permissionConversionHelper = new DefaultPermissionConversionHelper(session); return new RepositoryFileAce(sid, permissionConversionHelper.privilegesToPentahoPermissions(session, privileges)); } }