/* * Part of the CCNx Java Library. * * Copyright (C) 2009,2010 Palo Alto Research Center, Inc. * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 2.1 * as published by the Free Software Foundation. * This library 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 library; * if not, write to the Free Software Foundation, Inc., 51 Franklin Street, * Fifth Floor, Boston, MA 02110-1301 USA. */ package org.ccnx.ccn.profiles.namespace; import java.io.IOException; import java.util.HashSet; import java.util.Set; import org.ccnx.ccn.CCNHandle; import org.ccnx.ccn.config.SystemConfiguration; import org.ccnx.ccn.impl.support.Log; import org.ccnx.ccn.profiles.VersioningProfile; import org.ccnx.ccn.profiles.search.Pathfinder; import org.ccnx.ccn.profiles.search.Pathfinder.SearchResults; import org.ccnx.ccn.protocol.ContentName; /** * Maintains a list of existing policy marker prefixes. **/ public class NamespaceManager { protected static Set<ContentName> _searchedPathCache = new HashSet<ContentName>(); protected static Set<ContentName> _policyControlledNamespaces = new HashSet<ContentName>(); /** * Find the closest policy controlled namespace that cover operations on a specific name. * If none exists in memory than this searches up the name tree. * @throws IOException */ public static ContentName findPolicyControlledNamespace(ContentName controlledName, CCNHandle handle) throws IOException { // See if we already have a prefix controlling this name. for (ContentName prefix : _policyControlledNamespaces) { if (inProtectedNamespace(prefix, controlledName)) { // Doesn't handle nesting... want to find the longest match that matches this name, // while marking ones we don't have to search again. Works for now, might need to make // this more sophisticated if applications warrant. Log.info("Found policy control prefix {0} protecting {1}", prefix, controlledName); return prefix; } } // No known prefix exists for this name - now look to see if we can find a prefix up the path to create one... ContentName searchName = VersioningProfile.cutTerminalVersion(controlledName).first(); Log.info("No cached policy control prefix found, searching for root object for {0}. Removed terminal version, checking path {1}", controlledName, searchName); // Have a cache of searched paths, so we don't re-search. if (cacheContainsPath(searchName)) { Log.info("Cache indicates that we have already checked the path {0} for namespace roots, with none found. Returning null.", searchName); return null; } // Search up a path (towards the root) for an Access Control root marker Pathfinder pathfinder = new Pathfinder(searchName, null, NamespaceProfile.policyPostfix(), true, false, SystemConfiguration.SHORT_TIMEOUT, _searchedPathCache, handle); SearchResults results = pathfinder.waitForResults(); if (null != results.getExcluded()) { _searchedPathCache.addAll(results.getExcluded()); } if (null != results.getResult()) { ContentName policyPrefix = results.getResult().name().cut(results.getInterestName().count()); _policyControlledNamespaces.add(policyPrefix); return policyPrefix; } return null; } public synchronized static void clearSearchedPathCache() { _searchedPathCache.clear(); } public synchronized static void addToSearchedPathCache(Set<ContentName> newPaths) { _searchedPathCache.addAll(newPaths); } public synchronized static void removeFromSearchedPathCache(ContentName path) { _searchedPathCache.remove(path); } public static boolean cacheContainsPath(ContentName path) { // Need cache to contain everything on the path to be useful. while (_searchedPathCache.contains(path)) { if (path.equals(ContentName.ROOT)) { break; } path = path.parent(); } if (path.equals(ContentName.ROOT) && _searchedPathCache.contains(path)) { return true; } return false; } public static boolean inProtectedNamespace(ContentName namespace, ContentName content) { return namespace.isPrefixOf(content); } }