/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.jackrabbit.core.security.authorization.acl; import org.apache.jackrabbit.core.SessionImpl; import org.apache.jackrabbit.core.id.ItemId; import org.apache.jackrabbit.spi.Path; import org.apache.jackrabbit.spi.commons.conversion.PathResolver; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.jcr.RepositoryException; import java.util.Collection; import java.util.List; /** * <code>EntryFilterImpl</code>... */ class EntryFilterImpl implements EntryFilter { /** * logger instance */ private static final Logger log = LoggerFactory.getLogger(EntryFilterImpl.class); private final Collection<String> principalNames; private final PathProvider pathProvider; private String itemPath; EntryFilterImpl(Collection<String> principalNames, final ItemId id, final SessionImpl sessionImpl) { this.principalNames = principalNames; this.pathProvider = new PathProvider() { public String getPath() throws RepositoryException { Path p = sessionImpl.getHierarchyManager().getPath(id); return sessionImpl.getJCRPath(p); } }; } EntryFilterImpl(Collection<String> principalNames, final Path absPath, final PathResolver pathResolver) { this.principalNames = principalNames; this.pathProvider = new PathProvider() { public String getPath() throws RepositoryException { return pathResolver.getJCRPath(absPath); } }; } /** * Separately collect the entries defined for the user and group * principals. * * @param entries * @param resultLists * @see EntryFilter#filterEntries(java.util.List, java.util.List[]) */ public void filterEntries(List<Entry> entries, List<Entry>... resultLists) { if (resultLists.length == 2) { List<Entry> userAces = resultLists[0]; List<Entry> groupAces = resultLists[1]; int uInsertIndex = userAces.size(); int gInsertIndex = groupAces.size(); // first collect aces present on the given aclNode. for (Entry ace : entries) { // only process ace if 'principalName' is contained in the given set if (matches(ace)) { // add it to the proper list (e.g. separated by principals) /** * NOTE: access control entries must be collected in reverse * order in order to assert proper evaluation. */ if (ace.isGroupEntry()) { groupAces.add(gInsertIndex, ace); } else { userAces.add(uInsertIndex, ace); } } } } else { log.warn("Filtering aborted. Expected 2 result lists."); } } private boolean matches(Entry entry) { if (principalNames == null || principalNames.contains(entry.getPrincipalName())) { if (!entry.hasRestrictions()) { // short cut: there is no glob-restriction -> the entry matches // because it is either defined on the node or inherited. return true; } else { // there is a glob-restriction: check if the target path matches // this entry. try { return entry.matches(getPath()); } catch (RepositoryException e) { log.error("Cannot determine ACE match.", e); } } } // doesn't match this filter -> ignore return false; } String getPath() throws RepositoryException { if (itemPath == null) { itemPath = pathProvider.getPath(); } return itemPath; } //-------------------------------------------------------------------------- /** * Interface for lazy calculation of the JCR path used for evaluation of ACE * matching in case of entries defining restriction(s). */ private interface PathProvider { String getPath() throws RepositoryException; } }