/** * This file Copyright (c) 2003-2012 Magnolia International * Ltd. (http://www.magnolia-cms.com). All rights reserved. * * * This file is dual-licensed under both the Magnolia * Network Agreement and the GNU General Public License. * You may elect to use one or the other of these licenses. * * This file is distributed in the hope that it will be * useful, but AS-IS and WITHOUT ANY WARRANTY; without even the * implied warranty of MERCHANTABILITY or FITNESS FOR A * PARTICULAR PURPOSE, TITLE, or NONINFRINGEMENT. * Redistribution, except as permitted by whichever of the GPL * or MNA you select, is prohibited. * * 1. For the GPL license (GPL), you can redistribute and/or * modify this file under the terms of the GNU General * Public License, Version 3, as published by the Free Software * Foundation. You should have received a copy of the GNU * General Public License, Version 3 along with this program; * if not, write to the Free Software Foundation, Inc., 51 * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * 2. For the Magnolia Network Agreement (MNA), this file * and the accompanying materials are made available under the * terms of the MNA which accompanies this distribution, and * is available at http://www.magnolia-cms.com/mna.html * * Any modifications to this file must keep this entire header * intact. * */ package info.magnolia.cms.core.search; import info.magnolia.cms.core.Content; import info.magnolia.cms.core.DefaultContent; import info.magnolia.cms.core.HierarchyManager; import info.magnolia.cms.core.ItemType; import info.magnolia.cms.core.Path; import info.magnolia.cms.security.PermissionUtil; import java.util.ArrayList; import java.util.Collection; import java.util.Hashtable; import java.util.Map; import javax.jcr.Node; import javax.jcr.NodeIterator; import javax.jcr.RepositoryException; import javax.jcr.Session; import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Wrapping a JCR {@link javax.jcr.query.QueryResult}. This class will filter the result according * to the user's ACLs. You can use {@link #getContent(String)} to retrieve nodes of a certain type. * If the node's type doesn't match the nearest matching ancestors is add instead. This allows to * search in paragraph content while retrieving a list of pages. * * @version $Id$ * * @deprecated Since 4.5.4 we are using JCR query API. */ public class QueryResultImpl implements QueryResult { /** * Logger. */ private static Logger log = LoggerFactory.getLogger(QueryResultImpl.class); /** * Unfiltered result object. */ protected javax.jcr.query.QueryResult result; /** * caches all previously queried objects. */ protected Map<String, Collection<Content>> objectStore = new Hashtable<String, Collection<Content>>(); /** * TODO dlipp: Remove - it's not used internally. */ protected HierarchyManager hm; protected final long maxResultSize; protected Map<String, String> dirtyHandles = new Hashtable<String, String>(); protected QueryResultImpl(javax.jcr.query.QueryResult result, HierarchyManager hm) { this(result, hm, Long.MAX_VALUE); } protected QueryResultImpl(javax.jcr.query.QueryResult result, HierarchyManager hm, long maxResultSize) { this.result = result; this.hm = hm; this.maxResultSize = maxResultSize; } public javax.jcr.query.QueryResult getJcrResult() { return result; } /** * Adds all found nodes of a certain type. If the type doesn't match it will traverse the * ancestors and add them instead. */ protected void build(String nodeType, Collection<Content> collection) throws RepositoryException { this.objectStore.put(nodeType, collection); NodeIterator nodeIterator = this.result.getNodes(); // whitespace separated list (can't hurt since a single nodetype name can't contain a space) String[] nodeTypes = StringUtils.split(nodeType); while (collection.size() < maxResultSize && nodeIterator.hasNext()) { Node node = nodeIterator.nextNode(); try { build(node, nodeTypes, collection); } catch (RepositoryException re) { log.error("{} caught while iterating on query results: {}", re.getClass().getName(), re.getMessage()); if (log.isDebugEnabled()) { log.debug( re.getClass().getName() + " caught while iterating on query results: " + re.getMessage(), re); } } } } /** * Traverses the hierarchy from the current node to the root until the node's type matches. */ protected void build(Node node, String[] nodeType, Collection<Content> collection) throws RepositoryException { /** * All custom node types */ if ((nodeType == null || nodeType.length == 0) || isNodeType(node, nodeType) && !node.isNodeType(ItemType.NT_RESOURCE)) { if (this.dirtyHandles.get(node.getPath()) == null) { // TODO: yet another of those silly checks ... if we were not allowed, we would not have the node here boolean isAllowed = PermissionUtil.isGranted(node.getSession(), Path.getAbsolutePath(node.getPath()), Session.ACTION_READ); if (isAllowed) { collection.add(new DefaultContent(node)); this.dirtyHandles.put(node.getPath(), StringUtils.EMPTY); } } return; } if (node.getDepth() > 0) { this.build(node.getParent(), nodeType, collection); } } @Override public Collection<Content> getContent() { return getContent(ItemType.CONTENT.getSystemName()); } @Override public Collection<Content> getContent(String nodeType) { Collection<Content> resultSet = this.objectStore.get(nodeType); if (resultSet == null) { /* build it first time */ resultSet = new ArrayList<Content>(); try { this.build(nodeType, resultSet); } catch (RepositoryException re) { log.error(re.getMessage()); } } return resultSet; } private boolean isNodeType(Node node, String[] nodeType) throws RepositoryException { for (String nt : nodeType) { if (node.isNodeType(nt)) { return true; } } return false; } }