Author: mduerig Date: Fri Nov 5 17:53:57 2010 New Revision: 1031680 URL: http://svn.apache.org/viewvc?rev=1031680&view=rev Log: JCR-2800: Implement search facility for users and groups work in progress Added: jackrabbit/trunk/jackrabbit-api/src/main/java/org/apache/jackrabbit/api/security/user/Query.java jackrabbit/trunk/jackrabbit-api/src/main/java/org/apache/jackrabbit/api/security/user/QueryBuilder.java jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/XPathQueryBuilder.java jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/XPathQueryEvaluator.java jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/security/user/UserManagerSearchTest.java jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/iterator/Predicates.java Modified: jackrabbit/trunk/jackrabbit-api/src/main/java/org/apache/jackrabbit/api/security/user/UserManager.java jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/UserManagerImpl.java jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/security/user/TestAll.java jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/user/UserImporterTest.java Added: jackrabbit/trunk/jackrabbit-api/src/main/java/org/apache/jackrabbit/api/security/user/Query.java URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-api/src/main/java/org/apache/jackrabbit/api/security/user/Query.java?rev=1031680&view=auto ============================================================================== --- jackrabbit/trunk/jackrabbit-api/src/main/java/org/apache/jackrabbit/api/security/user/Query.java (added) +++ jackrabbit/trunk/jackrabbit-api/src/main/java/org/apache/jackrabbit/api/security/user/Query.java Fri Nov 5 17:53:57 2010 @@ -0,0 +1,50 @@ +/* + * 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.api.security.user; + +/** + * A query to match {@link Authorizable}s. Pass an instance of this interface to + * {@link UserManager#findAuthorizables(Query)}. + * + * The following query finds all users named 'Bob' which have the word + * 'engineer' in its description and returns them in ascending order wrt. to + * the name. + * + *
+ *  Iterator result = userMgr.findAuthorizables(new Query() {
+ *      public  void build(QueryBuilder builder) {
+ *          builder.setCondition(builder.
+ *              and(builder.
+ *                  property("@name", RelationOp.EQ, valueFactory.createValue("Bob")), builder.
+ *                  contains("@description", "engineer")));
+ *
+ *          builder.setSortOrder("@name", Direction.ASCENDING);
+ *          builder.setSelector(Selector.USER);
+ *      }
+ *  });
+ * 
+ */ +public interface Query { + + /** + * Build the query using a {@link QueryBuilder}. + * @param builder A query builder for building the query. + * @param Opaque type of the query builder. + */ + void build(QueryBuilder builder); +} Added: jackrabbit/trunk/jackrabbit-api/src/main/java/org/apache/jackrabbit/api/security/user/QueryBuilder.java URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-api/src/main/java/org/apache/jackrabbit/api/security/user/QueryBuilder.java?rev=1031680&view=auto ============================================================================== --- jackrabbit/trunk/jackrabbit-api/src/main/java/org/apache/jackrabbit/api/security/user/QueryBuilder.java (added) +++ jackrabbit/trunk/jackrabbit-api/src/main/java/org/apache/jackrabbit/api/security/user/QueryBuilder.java Fri Nov 5 17:53:57 2010 @@ -0,0 +1,207 @@ +/* + * 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.api.security.user; + +import javax.jcr.Value; + +public interface QueryBuilder { + + /** + * The sort order of the result set of a query. + */ + enum Direction { + ASCENDING("ascending"), + DESCENDING("descending"); + + private final String direction; + + Direction(String direction) { + this.direction = direction; + } + + public String getDirection() { + return direction; + } + } + + /** + * The selectors for a query. + */ + enum Selector { + AUTHORIZABLE("rep:Authorizable"), + USER("rep:User"), + GROUP("rep:Group"); + + private final String ntName; + + Selector(String ntName) { + this.ntName = ntName; + } + + public String getNtName() { + return ntName; + } + } + + /** + * Relational operators for comparing a property to a value. Correspond + * to the general comparison operators as define in JSR-170. + * The {@link #EX} tests for existence of a property. + */ + enum RelationOp { + NE("!="), + EQ("="), + LT("<"), + LE("<="), + GT(">"), + GE("=>"), + EX(""); + + private final String op; + + RelationOp(String op) { + this.op = op; + } + + public String getOp() { + return op; + } + } + + /** + * Set the selector for the query. + * + * @param selector One of {@link Selector#AUTHORIZABLE}, {@link Selector#USER} or {@link Selector#GROUP} + */ + void setSelector(Selector selector); + + /** + * Set the scope for the query. If set, the query will only return members of a specific group. + * + * @param groupName Name of the group to restrict the query to. + * @param declaredOnly If true only declared members of the groups are returned. + * Otherwise indirect memberships are also considered. + */ + void setScope(String groupName, boolean declaredOnly); + + /** + * Set the condition for the query. The query only includes {@link Authorizable}s + * for which this condition holds. + * + * @param condition Condition upon which Authorizables are included in the query result + */ + void setCondition(T condition); + + /** + * Set the sort order of the {@link Authorizable}s returned by the query. + * The format of the propertyName is the same as in XPath: + * @propertyName sorts on a property of the current node. + * relative/path/@propertyName sorts on a property of a + * descendant node. + * + * @param propertyName The name of the property to sort on + * @param direction Direction to sort. Either {@link Direction#ASCENDING} or {@link Direction#DESCENDING} + */ + void setSortOrder(String propertyName, Direction direction); + + /** + * Set the limit of the query. A limit consists of an offset, a maximal number of results + * to include and a direction. The offset refers to the value of the sort order property. + * If forward is true (false) the query returns + * at most the maxCount {@link Authorizable}s whose value of the sort order + * property follows (precedes)the specified offset in the given sort + * {@link Direction direction}. This method has no effect if the + * {@link #setSortOrder(String, Direction) sort order} is not also specified. + * @see #setSortOrder(String, Direction) + * + * @param offset Offset from where to start returning results. null for no offset + * @param maxCount Maximal number of results to return. -1 for all. + * @param forward If true return the following count records. + * Otherwise return the preceding count records wrt. offset. + */ + void setLimit(String offset, int maxCount, boolean forward); + + /** + * Create a condition which holds iff the node of an {@link Authorizable} has a + * property at relPath which relates to value through + * op. The format of the relPath argument is the same + * as in XPath: @attributeName for an attribute on this node and + * relative/path/@attributeName for an attribute of a descendant node. + * {@link RelationOp#EX} tests for existence of a property. In this case the + * value argument is ignored. + * + * @param relPath Relative path from the authorizable's node to the property + * @param op Comparison operator + * @param value Value to compare the property at relPath to + * @return A condition + */ + T property(String relPath, RelationOp op, Value value); + + /** + * Create a full text search condition. The condition holds iff the node of an + * {@link Authorizable} has a property at relPath for which + * searchExpr yields results. + * The format of the relPath argument is the same as in XPath: + * . searches all properties of the current node, @attributeName + * searches the attributeName property of the current node, relative/path/. + * searches all properties of the descendant node at relative/path and + * relative/path/@attributeName searches the attributeName property + * of the descendant node at relative/path. + * The syntax of searchExpr is
[-]value { [OR] [-]value }
. + * + * @param relPath Relative path from the authorizable's node to the property + * @param searchExpr A full text search expression + * @return A condition + */ + T contains(String relPath, String searchExpr); + + /** + * Create a condition which holds for {@link Authorizable}s which can impersonate as + * name. + * + * @param name Name of an authorizable + * @return A condition + */ + T impersonates(String name); + + /** + * Return a condition which holds iff condition does not hold. + * + * @param condition Condition to negate + * @return A condition + */ + T not(T condition); + + /** + * Return a condition which holds iff both sub conditions hold. + * + * @param condition1 first sub condition + * @param condition2 second sub condition + * @return A condition + */ + T and(T condition1, T condition2); + + /** + * Return a condition which holds iff any of the two sub conditions hold. + * + * @param condition1 first sub condition + * @param condition2 second sub condition + * @return A condition + */ + T or(T condition1, T condition2); +} Modified: jackrabbit/trunk/jackrabbit-api/src/main/java/org/apache/jackrabbit/api/security/user/UserManager.java URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-api/src/main/java/org/apache/jackrabbit/api/security/user/UserManager.java?rev=1031680&r1=1031679&r2=1031680&view=diff ============================================================================== --- jackrabbit/trunk/jackrabbit-api/src/main/java/org/apache/jackrabbit/api/security/user/UserManager.java (original) +++ jackrabbit/trunk/jackrabbit-api/src/main/java/org/apache/jackrabbit/api/security/user/UserManager.java Fri Nov 5 17:53:57 2010 @@ -111,6 +111,15 @@ public interface UserManager { Iterator findAuthorizables(String relPath, String value, int searchType) throws RepositoryException; /** + * Return {@link Authorizable}s that match a specific {@link Query}. + * + * @param query A query + * @return Iterator of authorizables witch match the query. + * @throws RepositoryException If an error occurs. + */ + Iterator findAuthorizables(Query query) throws RepositoryException; + + /** * Creates an User for the given userID / password pair; neither of the * specified parameters can be null.
* Same as {@link #createUser(String,String,Principal,String)} where Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/UserManagerImpl.java URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/UserManagerImpl.java?rev=1031680&r1=1031679&r2=1031680&view=diff ============================================================================== --- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/UserManagerImpl.java (original) +++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/UserManagerImpl.java Fri Nov 5 17:53:57 2010 @@ -17,16 +17,8 @@ package org.apache.jackrabbit.core.security.user; import org.apache.jackrabbit.api.security.principal.ItemBasedPrincipal; -import org.apache.jackrabbit.api.security.user.Authorizable; -import org.apache.jackrabbit.api.security.user.AuthorizableExistsException; -import org.apache.jackrabbit.api.security.user.Group; -import org.apache.jackrabbit.api.security.user.User; -import org.apache.jackrabbit.api.security.user.UserManager; -import org.apache.jackrabbit.core.ItemImpl; -import org.apache.jackrabbit.core.NodeImpl; -import org.apache.jackrabbit.core.ProtectedItemModifier; -import org.apache.jackrabbit.core.SessionImpl; -import org.apache.jackrabbit.core.SessionListener; +import org.apache.jackrabbit.api.security.user.*; +import org.apache.jackrabbit.core.*; import org.apache.jackrabbit.core.id.NodeId; import org.apache.jackrabbit.core.security.SystemPrincipal; import org.apache.jackrabbit.core.security.principal.PrincipalImpl; @@ -37,26 +29,13 @@ import org.apache.jackrabbit.util.Text; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import javax.jcr.AccessDeniedException; -import javax.jcr.ItemExistsException; -import javax.jcr.ItemNotFoundException; -import javax.jcr.Node; -import javax.jcr.NodeIterator; -import javax.jcr.RepositoryException; -import javax.jcr.UnsupportedRepositoryOperationException; -import javax.jcr.Value; +import javax.jcr.*; import javax.jcr.lock.LockException; import javax.jcr.nodetype.ConstraintViolationException; import javax.jcr.version.VersionException; - import java.io.UnsupportedEncodingException; import java.security.Principal; -import java.util.HashSet; -import java.util.Iterator; -import java.util.NoSuchElementException; -import java.util.Properties; -import java.util.Set; -import java.util.UUID; +import java.util.*; /** * Default implementation of the UserManager interface with the @@ -487,6 +466,12 @@ public class UserManagerImpl extends Pro return new AuthorizableIterator(nodes); } + public Iterator findAuthorizables(Query query) throws RepositoryException { + XPathQueryBuilder builder = new XPathQueryBuilder(); + query.build(builder); + return new XPathQueryEvaluator(builder, this, session.getWorkspace().getQueryManager()).eval(); + } + /** * @see UserManager#createUser(String,String) */ Added: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/XPathQueryBuilder.java URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/XPathQueryBuilder.java?rev=1031680&view=auto ============================================================================== --- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/XPathQueryBuilder.java (added) +++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/XPathQueryBuilder.java Fri Nov 5 17:53:57 2010 @@ -0,0 +1,264 @@ +/* + * 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.user; + +import org.apache.jackrabbit.api.security.user.QueryBuilder; + +import javax.jcr.RepositoryException; +import javax.jcr.Value; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +public class XPathQueryBuilder implements QueryBuilder { + + interface Condition { + void accept(ConditionVisitor visitor) throws RepositoryException; + } + + interface ConditionVisitor { + void visit(PropertyCondition condition) throws RepositoryException; + void visit(ContainsCondition condition); + void visit(ImpersonationCondition condition); + void visit(NotCondition condition) throws RepositoryException; + void visit(AndCondition condition) throws RepositoryException; + void visit(OrCondition condition) throws RepositoryException; + } + + private Selector selector = Selector.AUTHORIZABLE; + private String groupName; + private boolean declaredMembersOnly; + private Condition condition; + private String sortProperty; + private Direction sortDirection = Direction.ASCENDING; + private String offset; + private int maxCount = -1; + private boolean forward = true; + + Selector getSelector() { + return selector; + } + + public String getGroupName() { + return groupName; + } + + public boolean isDeclaredMembersOnly() { + return declaredMembersOnly; + } + + Condition getCondition() { + return condition; + } + + String getSortProperty() { + return sortProperty; + } + + Direction getSortDirection() { + return sortDirection; + } + + String getOffset() { + return offset; + } + + int getMaxCount() { + return maxCount; + } + + boolean isForward() { + return forward; + } + + //------------------------------------------< QueryBuilder >--- + + public void setSelector(Selector selector) { + this.selector = selector; + } + + public void setScope(String groupName, boolean declaredOnly) { + this.groupName = groupName; + declaredMembersOnly = declaredOnly; + } + + public void setCondition(Condition condition) { + this.condition = condition; + } + + public void setSortOrder(String propertyName, Direction direction) { + sortProperty = propertyName; + sortDirection = direction; + } + + public void setLimit(String offset, int maxCount, boolean forward) { + this.offset = offset; + this.maxCount = maxCount; + this.forward = true; + throw new UnsupportedOperationException("limit is not yet supported"); // todo implement: limit + } + + public Condition property(String relPath, RelationOp op, Value value) { + return new PropertyCondition(relPath, op, value); + } + + public Condition contains(String relPath, String searchExpr) { + return new ContainsCondition(relPath, searchExpr); + } + + public Condition impersonates(String name) { + return new ImpersonationCondition(name); + } + + public Condition not(Condition condition) { + return new NotCondition(condition); + } + + public Condition and(Condition condition1, Condition condition2) { + return new AndCondition(condition1, condition2); + } + + public Condition or(Condition condition1, Condition condition2) { + return new OrCondition(condition1, condition2); + } + + //------------------------------------------< private >--- + + static class PropertyCondition implements Condition { + private final String relPath; + private final RelationOp op; + private final Value value; + + public PropertyCondition(String relPath, RelationOp op, Value value) { + this.relPath = relPath; + this.op = op; + this.value = value; + } + + public String getRelPath() { + return relPath; + } + + public RelationOp getOp() { + return op; + } + + public Value getValue() { + return value; + } + + public void accept(ConditionVisitor visitor) throws RepositoryException { + visitor.visit(this); + } + } + + static class ContainsCondition implements Condition { + private final String relPath; + private final String searchExpr; + + public ContainsCondition(String relPath, String searchExpr) { + this.relPath = relPath; + this.searchExpr = searchExpr; + } + + public String getRelPath() { + return relPath; + } + + public String getSearchExpr() { + return searchExpr; + } + + public void accept(ConditionVisitor visitor) { + visitor.visit(this); + } + } + + static class ImpersonationCondition implements Condition { + private final String name; + + public ImpersonationCondition(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public void accept(ConditionVisitor visitor) { + visitor.visit(this); + } + } + + static class NotCondition implements Condition { + private final Condition condition; + + public NotCondition(Condition condition) { + this.condition = condition; + } + + public Condition getCondition() { + return condition; + } + + public void accept(ConditionVisitor visitor) throws RepositoryException { + visitor.visit(this); + } + } + + abstract static class CompoundCondition implements Condition, Iterable { + private final List conditions = new ArrayList(); + + public CompoundCondition() { + super(); + } + + public CompoundCondition(Condition condition1, Condition condition2) { + conditions.add(condition1); + conditions.add(condition2); + } + + public void addCondition(Condition condition) { + conditions.add(condition); + } + + public Iterator iterator() { + return conditions.iterator(); + } + } + + static class AndCondition extends CompoundCondition { + public AndCondition(Condition condition1, Condition condition2) { + super(condition1, condition2); + } + + public void accept(ConditionVisitor visitor) throws RepositoryException { + visitor.visit(this); + } + } + + static class OrCondition extends CompoundCondition { + public OrCondition(Condition condition1, Condition condition2) { + super(condition1, condition2); + } + + public void accept(ConditionVisitor visitor) throws RepositoryException { + visitor.visit(this); + } + } +} Added: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/XPathQueryEvaluator.java URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/XPathQueryEvaluator.java?rev=1031680&view=auto ============================================================================== --- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/XPathQueryEvaluator.java (added) +++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/XPathQueryEvaluator.java Fri Nov 5 17:53:57 2010 @@ -0,0 +1,237 @@ +/* + * 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.user; + +import org.apache.jackrabbit.api.security.user.Authorizable; +import org.apache.jackrabbit.api.security.user.Group; +import org.apache.jackrabbit.api.security.user.QueryBuilder.RelationOp; +import org.apache.jackrabbit.core.NodeImpl; +import org.apache.jackrabbit.spi.commons.iterator.Iterators; +import org.apache.jackrabbit.spi.commons.iterator.Predicate; +import org.apache.jackrabbit.spi.commons.iterator.Predicates; +import org.apache.jackrabbit.spi.commons.iterator.Transformer; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.jcr.Node; +import javax.jcr.PropertyType; +import javax.jcr.RepositoryException; +import javax.jcr.Value; +import javax.jcr.query.Query; +import javax.jcr.query.QueryManager; +import java.util.Iterator; + +/** + * This evaluator for {@link org.apache.jackrabbit.api.security.user.Query}s use XPath + * and some minimal client side filtering. + */ +public class XPathQueryEvaluator implements XPathQueryBuilder.ConditionVisitor { + static final Logger log = LoggerFactory.getLogger(XPathQueryEvaluator.class); + + private final XPathQueryBuilder builder; + private final UserManagerImpl userManager; + private final QueryManager queryManager; + private final StringBuilder xPath = new StringBuilder(); + + public XPathQueryEvaluator(XPathQueryBuilder builder, UserManagerImpl userManager, QueryManager queryManager) { + this.builder = builder; + this.userManager = userManager; + this.queryManager = queryManager; + } + + public Iterator eval() throws RepositoryException { + xPath.append("//element(*,") + .append(builder.getSelector().getNtName()) + .append(')'); + + XPathQueryBuilder.Condition condition = builder.getCondition(); + if (condition != null) { + xPath.append('['); + condition.accept(this); + xPath.append(']'); + } + + String sortCol = builder.getSortProperty(); + if (sortCol != null) { + xPath.append(" order by ") + .append(sortCol) + .append(' ') + .append(builder.getSortDirection().getDirection()); + } + + Query query = queryManager.createQuery(xPath.toString(), Query.XPATH); + int count = builder.getMaxCount(); + if (count == 0) { + return Iterators.empty(); + } + + if (count > 0) { + query.setLimit(count); + } + + return filter(toAuthorizables(execute(query)), builder.getGroupName(), builder.isDeclaredMembersOnly()); + } + + //------------------------------------------< ConditionVisitor >--- + + public void visit(XPathQueryBuilder.PropertyCondition condition) throws RepositoryException { + RelationOp relOp = condition.getOp(); + if (relOp == RelationOp.EX) { + xPath.append(condition.getRelPath()); + } + else { + xPath.append(condition.getRelPath()) + .append(condition.getOp().getOp()) + .append(format(condition.getValue())); + } + } + + public void visit(XPathQueryBuilder.ContainsCondition condition) { + xPath.append("jcr:contains(") + .append(condition.getRelPath()) + .append(",'") + .append(condition.getSearchExpr()) + .append("')"); + } + + public void visit(XPathQueryBuilder.ImpersonationCondition condition) { + xPath.append("@rep:impersonators='") + .append(condition.getName()) + .append('\''); + } + + public void visit(XPathQueryBuilder.NotCondition condition) throws RepositoryException { + xPath.append("not("); + condition.getCondition().accept(this); + xPath.append(')'); + } + + public void visit(XPathQueryBuilder.AndCondition condition) throws RepositoryException { + int count = 0; + for (XPathQueryBuilder.Condition c : condition) { + xPath.append(count++ > 0 ? " and " : ""); + c.accept(this); + } + } + + public void visit(XPathQueryBuilder.OrCondition condition) throws RepositoryException { + int pos = xPath.length(); + + int count = 0; + for (XPathQueryBuilder.Condition c : condition) { + xPath.append(count++ > 0 ? " or " : ""); + c.accept(this); + } + + // Surround or clause with parentheses if it contains more than one term + if (count > 1) { + xPath.insert(pos, '('); + xPath.append(')'); + } + } + + //------------------------------------------< private >--- + + private static String format(Value value) throws RepositoryException { + switch (value.getType()) { + case PropertyType.STRING: + case PropertyType.BOOLEAN: + return '\'' + value.getString() + '\''; + + case PropertyType.LONG: + case PropertyType.DOUBLE: + return value.getString(); + + case PropertyType.DATE: + return "xs:dateTime('" + value.getString() + "')"; + + default: + throw new RepositoryException("Property of type " + PropertyType.nameFromValue(value.getType()) + + " not supported"); + } + } + + @SuppressWarnings("unchecked") + private static Iterator execute(Query query) throws RepositoryException { + return query.execute().getNodes(); + } + + private Iterator toAuthorizables(Iterator nodes) { + Transformer transformer = new Transformer() { + public Authorizable transform(Node node) { + try { + return userManager.getAuthorizable((NodeImpl) node); + } catch (RepositoryException e) { + log.warn("Cannot create authorizable from node {}", node); + log.debug(e.getMessage(), e); + return null; + } + } + }; + + return Iterators.transformIterator(nodes, transformer); + } + + private Iterator filter(Iterator authorizables, String groupName, + boolean declaredMembersOnly) throws RepositoryException { + + Predicate predicate; + if (groupName == null) { + predicate = Predicates.TRUE(); + } + else { + Authorizable groupAuth = userManager.getAuthorizable(groupName); + if (groupAuth == null || !groupAuth.isGroup()) { + predicate = Predicates.FALSE(); + } + else { + final Group group = (Group) groupAuth; + if (declaredMembersOnly) { + predicate = new Predicate() { + public boolean evaluate(Authorizable authorizable) { + try { + return authorizable != null && group.isDeclaredMember(authorizable); + } catch (RepositoryException e) { + log.warn("Cannot determine whether {} is member of group {}", authorizable, group); + log.debug(e.getMessage(), e); + return false; + } + } + }; + + } + else { + predicate = new Predicate() { + public boolean evaluate(Authorizable authorizable) { + try { + return authorizable != null && group.isMember(authorizable); + } catch (RepositoryException e) { + log.warn("Cannot determine whether {} is member of group {}", authorizable, group); + log.debug(e.getMessage(), e); + return false; + } + } + }; + } + } + } + + return Iterators.filterIterator(authorizables, predicate); + } + +} Modified: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/security/user/TestAll.java URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/security/user/TestAll.java?rev=1031680&r1=1031679&r2=1031680&view=diff ============================================================================== --- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/security/user/TestAll.java (original) +++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/security/user/TestAll.java Fri Nov 5 17:53:57 2010 @@ -41,6 +41,7 @@ public class TestAll extends TestCase { suite.addTestSuite(GroupTest.class); suite.addTestSuite(NestedGroupTest.class); suite.addTestSuite(ImpersonationTest.class); + suite.addTestSuite(UserManagerSearchTest.class); return suite; } Added: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/security/user/UserManagerSearchTest.java URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/security/user/UserManagerSearchTest.java?rev=1031680&view=auto ============================================================================== --- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/security/user/UserManagerSearchTest.java (added) +++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/security/user/UserManagerSearchTest.java Fri Nov 5 17:53:57 2010 @@ -0,0 +1,628 @@ +/* + * 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.api.security.user; + +import org.apache.jackrabbit.api.security.user.QueryBuilder.RelationOp; +import org.apache.jackrabbit.api.security.user.QueryBuilder.Selector; +import org.apache.jackrabbit.api.security.user.QueryBuilder.Direction; +import org.apache.jackrabbit.spi.commons.iterator.Iterators; +import org.apache.jackrabbit.spi.commons.iterator.Predicate; + +import javax.jcr.RepositoryException; +import javax.jcr.Value; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Set; + +public class UserManagerSearchTest extends AbstractUserTest { + + // users + private User blackWidow; + private User gardenSpider; + private User jumpingSpider; + private User ant; + private User bee; + private User fly; + private User jackrabbit; + private User deer; + private User opposum; + private User kangaroo; + private User elephant; + private User lemur; + private User gibbon; + private User crocodile; + private User turtle; + private User lizard; + private User kestrel; + private User goose; + private User pelican; + private User dove; + private User salamander; + private User goldenToad; + private User poisonDartFrog; + + private final Set users = new HashSet(); + + // groups + private Group animals; + private Group invertebrates; + private Group arachnids; + private Group insects; + private Group vertebrates; + private Group mammals; + private Group apes; + private Group reptiles; + private Group birds; + private Group amphibians; + + private final Set groups = new HashSet(); + private final Set authorizables = new HashSet(); + + @Override + public void setUp() throws Exception { + super.setUp(); + + // Create a zoo. Please excuse my ignorance in zoology ;-) + animals = createGroup("animals"); + invertebrates = createGroup("invertebrates"); + arachnids = createGroup("arachnids"); + insects = createGroup("insects"); + vertebrates = createGroup("vertebrates"); + mammals = createGroup("mammals"); + apes = createGroup("apes"); + reptiles = createGroup("reptiles"); + birds = createGroup("birds"); + amphibians = createGroup("amphibians"); + + animals.addMember(invertebrates); + animals.addMember(vertebrates); + invertebrates.addMember(arachnids); + invertebrates.addMember(insects); + vertebrates.addMember(mammals); + vertebrates.addMember(reptiles); + vertebrates.addMember(birds); + vertebrates.addMember(amphibians); + mammals.addMember(apes); + + blackWidow = createUser("black widow", "flies", 2, false); + gardenSpider = createUser("garden spider", "flies", 2, false); + jumpingSpider = createUser("jumping spider", "insects", 1, false); + addMembers(arachnids, blackWidow, gardenSpider, jumpingSpider); + + ant = createUser("ant", "leaves", 0.5, false); + bee = createUser("bee", "honey", 2.5, true); + fly = createUser("fly", "dirt", 1.3, false); + addMembers(insects, ant, bee, fly); + + jackrabbit = createUser("jackrabbit", "carrots", 2500, true); + deer = createUser("deer", "leaves", 120000, true); + opposum = createUser("opposum", "fruit", 1200, true); + kangaroo = createUser("kangaroo", "grass", 80000, true); + elephant = createUser("elephant", "leaves", 5000000, true); + addMembers(mammals, jackrabbit, deer, opposum, kangaroo, elephant); + + lemur = createUser("lemur", "nectar", 1100, true); + gibbon = createUser("gibbon", "meat", 20000, true); + addMembers(apes, lemur, gibbon); + + crocodile = createUser("crocodile", "meat", 80000, false); + turtle = createUser("turtle", "leaves", 10000, true); + lizard = createUser("lizard", "leaves", 2000, false); + addMembers(reptiles, crocodile, turtle, lizard); + + kestrel = createUser("kestrel", "mice", 2000, false); + goose = createUser("goose", "snails", 10000, true); + pelican = createUser("pelican", "fish", 15000, true); + dove = createUser("dove", "insects", 1600, false); + addMembers(birds, kestrel, goose, pelican, dove); + + salamander = createUser("salamander", "insects", 800, true); + goldenToad = createUser("golden toad", "insects", 700, false); + poisonDartFrog = createUser("poison dart frog", "insects", 40, false); + addMembers(amphibians, salamander, goldenToad, poisonDartFrog); + + setProperty("canFly", vf.createValue(true), bee, fly, kestrel, goose, pelican, dove); + setProperty("poisonous",vf.createValue(true), blackWidow, bee, poisonDartFrog ); + setProperty("poisonous", vf.createValue(false), turtle, lemur); + setProperty("hasWings", vf.createValue(false), blackWidow, gardenSpider, jumpingSpider, ant, + jackrabbit, deer, opposum, kangaroo, elephant, lemur, gibbon, crocodile, turtle, lizard, + salamander, goldenToad, poisonDartFrog); + setProperty("color", vf.createValue("black"), blackWidow, gardenSpider, ant, fly, lizard, salamander); + setProperty("color", vf.createValue("white"), opposum, goose, pelican, dove); + setProperty("color", vf.createValue("gold"), goldenToad); + setProperty("numberOfLegs", vf.createValue(2), kangaroo, gibbon, kestrel, goose, dove); + setProperty("numberOfLegs", vf.createValue(4), jackrabbit, deer, opposum, elephant, lemur, crocodile, + turtle, lizard, salamander, goldenToad, poisonDartFrog); + setProperty("numberOfLegs", vf.createValue(6), ant, bee, fly); + setProperty("numberOfLegs", vf.createValue(8), blackWidow, gardenSpider, jumpingSpider); + + elephant.getImpersonation().grantImpersonation(jackrabbit.getPrincipal()); + + authorizables.addAll(users); + authorizables.addAll(groups); + + if (!userMgr.isAutoSave()) { + superuser.save(); + } + + } + + @Override + public void tearDown() throws Exception { + for (Authorizable authorizable : authorizables) { + authorizable.remove(); + } + authorizables.clear(); + groups.clear(); + users.clear(); + + if (!userMgr.isAutoSave()) { + superuser.save(); + } + + super.tearDown(); + } + + public void testAny() throws RepositoryException { + Iterator result = userMgr.findAuthorizables(new Query() { + public void build(QueryBuilder builder) { /* any */ } + }); + + assertContainsAll(result, authorizables.iterator()); + } + + public void testSelector() throws RepositoryException { + for (final Selector s : Selector.values()) { + Iterator result = userMgr.findAuthorizables(new Query() { + public void build(QueryBuilder builder) { + builder.setSelector(s); + } + }); + + switch (s) { + case AUTHORIZABLE: + assertContainsAll(result, authorizables.iterator()); + break; + + case USER: + assertContainsAll(result, users.iterator()); + break; + + case GROUP: + assertContainsAll(result, groups.iterator()); + break; + + default: + fail("Fall through in switch"); + } + + } + } + + public void testDirectScope() throws RepositoryException { + Group[] groups = new Group[]{mammals, vertebrates, apes}; + for (final Group g : groups) { + Iterator result = userMgr.findAuthorizables(new Query() { + public void build(QueryBuilder builder) { + try { + builder.setScope(g.getID(), true); + } catch (RepositoryException e) { + fail(e.getMessage()); + } + } + }); + + Iterator members = g.getDeclaredMembers(); + assertSameElements(result, members); + } + } + + public void testIndirectScope() throws RepositoryException { + Group[] groups = new Group[]{mammals, vertebrates, apes}; + for (final Group g : groups) { + Iterator result = userMgr.findAuthorizables(new Query() { + public void build(QueryBuilder builder) { + try { + builder.setScope(g.getID(), false); + } catch (RepositoryException e) { + fail(e.getMessage()); + } + } + }); + + Iterator members = g.getMembers(); + assertSameElements(result, members); + } + } + + public void testFindUsersInGroup() throws RepositoryException { + Group[] groups = new Group[]{mammals, vertebrates, apes}; + for (final Group g : groups) { + Iterator result = userMgr.findAuthorizables(new Query() { + public void build(QueryBuilder builder) { + try { + builder.setSelector(Selector.USER); + builder.setScope(g.getID(), false); + } catch (RepositoryException e) { + fail(e.getMessage()); + } + } + }); + + Iterator members = g.getMembers(); + Iterator users = Iterators.filterIterator(members, new Predicate() { + public boolean evaluate(Authorizable authorizable) { + return !authorizable.isGroup(); + } + }); + assertSameElements(result, users); + } + } + + public void testFindGroupsInGroup() throws RepositoryException { + Group[] groups = new Group[]{mammals, vertebrates, apes}; + for (final Group g : groups) { + Iterator result = userMgr.findAuthorizables(new Query() { + public void build(QueryBuilder builder) { + try { + builder.setSelector(Selector.GROUP); + builder.setScope(g.getID(), true); + } catch (RepositoryException e) { + fail(e.getMessage()); + } + } + }); + + Iterator members = g.getDeclaredMembers(); + Iterator users = Iterators.filterIterator(members, new Predicate() { + public boolean evaluate(Authorizable authorizable) { + return authorizable.isGroup(); + } + }); + assertSameElements(result, users); + } + } + + public void testFindProperty1() throws RepositoryException { + Iterator result = userMgr.findAuthorizables(new Query() { + public void build(QueryBuilder builder) { + builder.setCondition(builder. + property("@canFly", RelationOp.EQ, vf.createValue(true))); + } + }); + + Iterator expected = Iterators.filterIterator(users.iterator(), new Predicate() { + public boolean evaluate(User user) { + try { + Value[] canFly = user.getProperty("canFly"); + return canFly != null && canFly.length == 1 && canFly[0].getBoolean(); + } catch (RepositoryException e) { + fail(e.getMessage()); + } + return false; + } + }); + + assertTrue(result.hasNext()); + assertSameElements(result, expected); + } + + public void testFindProperty2() throws RepositoryException { + Iterator result = userMgr.findAuthorizables(new Query() { + public void build(QueryBuilder builder) { + builder.setCondition(builder. + property("profile/@weight", RelationOp.GT, vf.createValue(2000.0))); + } + }); + + Iterator expected = Iterators.filterIterator(users.iterator(), new Predicate() { + public boolean evaluate(User user) { + try { + Value[] weight = user.getProperty("profile/weight"); + return weight != null && weight.length == 1 && weight[0].getDouble() > 2000.0; + } catch (RepositoryException e) { + fail(e.getMessage()); + } + return false; + } + }); + + assertTrue(result.hasNext()); + assertSameElements(result, expected); + } + + public void testFindProperty3() throws RepositoryException { + Iterator result = userMgr.findAuthorizables(new Query() { + public void build(QueryBuilder builder) { + builder.setCondition(builder. + property("@numberOfLegs", RelationOp.EQ, vf.createValue(8))); + } + }); + + Iterator expected = Iterators.filterIterator(users.iterator(), new Predicate() { + public boolean evaluate(User user) { + try { + Value[] numberOfLegs = user.getProperty("numberOfLegs"); + return numberOfLegs != null && numberOfLegs.length == 1 && numberOfLegs[0].getLong() == 8; + } catch (RepositoryException e) { + fail(e.getMessage()); + } + return false; + } + }); + + assertTrue(result.hasNext()); + assertSameElements(result, expected); + } + + public void testPropertyExistence() throws RepositoryException { + Iterator result = userMgr.findAuthorizables(new Query() { + public void build(QueryBuilder builder) { + builder.setCondition(builder. + property("@poisonous", RelationOp.EX, null)); + } + }); + + Iterator expected = Iterators.filterIterator(users.iterator(), new Predicate() { + public boolean evaluate(User user) { + try { + Value[] poisonous = user.getProperty("poisonous"); + return poisonous != null && poisonous.length == 1; + } catch (RepositoryException e) { + fail(e.getMessage()); + } + return false; + } + }); + + assertTrue(result.hasNext()); + assertSameElements(result, expected); + } + + public void testContains1() throws RepositoryException { + Iterator result = userMgr.findAuthorizables(new Query() { + public void build(QueryBuilder builder) { + builder.setCondition(builder. + contains(".", "gold")); + } + }); + + Iterator expected = Iterators.singleton(goldenToad); + assertTrue(result.hasNext()); + assertSameElements(result, expected); + } + + public void testContains2() throws RepositoryException { + Iterator result = userMgr.findAuthorizables(new Query() { + public void build(QueryBuilder builder) { + builder.setCondition(builder. + contains("@color", "gold")); + } + }); + + Iterator expected = Iterators.singleton(goldenToad); + assertTrue(result.hasNext()); + assertSameElements(result, expected); + } + + public void testContains3() throws RepositoryException { + Iterator result = userMgr.findAuthorizables(new Query() { + public void build(QueryBuilder builder) { + builder.setCondition(builder. + contains("profile/.", "grass")); + } + }); + + Iterator expected = Iterators.singleton(kangaroo); + assertTrue(result.hasNext()); + assertSameElements(result, expected); + } + + public void testContains4() throws RepositoryException { + Iterator result = userMgr.findAuthorizables(new Query() { + public void build(QueryBuilder builder) { + builder.setCondition(builder. + contains("profile/@food", "grass")); + } + }); + + Iterator expected = Iterators.singleton(kangaroo); + assertTrue(result.hasNext()); + assertSameElements(result, expected); + } + + public void testCondition1() throws RepositoryException { + Iterator result = userMgr.findAuthorizables(new Query() { + public void build(QueryBuilder builder) { + builder.setCondition(builder. + and(builder. + property("profile/@cute", RelationOp.EQ, vf.createValue(true)), builder. + not(builder. + property("@color", RelationOp.EQ, vf.createValue("black"))))); + } + }); + + Iterator expected = Iterators.filterIterator(users.iterator(), new Predicate() { + public boolean evaluate(User user) { + try { + Value[] cute = user.getProperty("profile/cute"); + Value[] black = user.getProperty("color"); + return cute != null && cute.length == 1 && cute[0].getBoolean() && + !(black != null && black.length == 1 && black[0].getString().equals("black")); + } catch (RepositoryException e) { + fail(e.getMessage()); + } + return false; + } + }); + + assertTrue(result.hasNext()); + assertSameElements(result, expected); + } + + public void testCondition2() throws RepositoryException { + Iterator result = userMgr.findAuthorizables(new Query() { + public void build(QueryBuilder builder) { + builder.setCondition(builder. + or(builder. + property("profile/@food", RelationOp.EQ, vf.createValue("mice")), builder. + property("profile/@food", RelationOp.EQ, vf.createValue("nectar")))); + } + }); + + Iterator expected = Iterators.filterIterator(users.iterator(), new Predicate() { + public boolean evaluate(User user) { + try { + Value[] food = user.getProperty("profile/food"); + return food != null && food.length == 1 && + (food[0].getString().equals("mice") || food[0].getString().equals("nectar")); + } catch (RepositoryException e) { + fail(e.getMessage()); + } + return false; + } + }); + + assertTrue(result.hasNext()); + assertSameElements(result, expected); + } + + public void testImpersonation() throws RepositoryException { + Iterator result = userMgr.findAuthorizables(new Query() { + public void build(QueryBuilder builder) { + builder.setCondition(builder. + impersonates("jackrabbit")); + } + }); + + Iterator expected = Iterators.singleton(elephant); + assertTrue(result.hasNext()); + assertSameElements(result, expected); + } + + public void testSortOrder1() throws RepositoryException { + Iterator result = userMgr.findAuthorizables(new Query() { + public void build(QueryBuilder builder) { + builder.setCondition( + builder.property("@color", RelationOp.EX, null)); + builder.setSortOrder("@color", Direction.DESCENDING); + } + }); + + assertTrue(result.hasNext()); + String prev = null; + while (result.hasNext()) { + Authorizable authorizable = result.next(); + Value[] color = authorizable.getProperty("color"); + assertNotNull(color); + assertEquals(1, color.length); + assertTrue(prev == null || prev.compareTo(color[0].getString()) >= 0); + prev = color[0].getString(); + } + } + + public void testSortOrder2() throws RepositoryException { + Iterator result = userMgr.findAuthorizables(new Query() { + public void build(QueryBuilder builder) { + builder.setCondition( + builder.property("profile/@weight", RelationOp.EX, null)); + builder.setSortOrder("profile/@weight", Direction.ASCENDING); + } + }); + + assertTrue(result.hasNext()); + double prev = Double.MIN_VALUE; + while (result.hasNext()) { + Authorizable authorizable = result.next(); + Value[] weight = authorizable.getProperty("profile/weight"); + assertNotNull(weight); + assertEquals(1, weight.length); + assertTrue(prev <= weight[0].getDouble()); + prev = weight[0].getDouble(); + } + } + + //------------------------------------------< private >--- + + private static void addMembers(Group group, Authorizable... authorizables) throws RepositoryException { + for (Authorizable authorizable : authorizables) { + group.addMember(authorizable); + } + } + + private Group createGroup(String name) throws RepositoryException { + Group group = userMgr.createGroup(name); + groups.add(group); + return group; + } + + private User createUser(String name, String food, double weight, boolean cute) throws RepositoryException { + User user = userMgr.createUser(name, ""); + user.setProperty("profile/food", vf.createValue(food)); + user.setProperty("profile/weight", vf.createValue(weight)); + user.setProperty("profile/cute", vf.createValue(cute)); + users.add(user); + return user; + } + + private static void setProperty(String relPath, Value value, Authorizable... authorizables) throws RepositoryException { + for (Authorizable authorizable : authorizables) { + authorizable.setProperty(relPath, value); + } + } + + private static void assertContainsAll(Iterator it1, Iterator it2) { + Set set1 = toSet(it1); + Set set2 = toSet(it2); + set2.removeAll(set1); + if (!set2.isEmpty()) { + fail("Missing elements in query result: " + set2); + } + } + + private static void assertSameElements(Iterator it1, Iterator it2) { + Set set1 = toSet(it1); + Set set2 = toSet(it2); + + Set missing = new HashSet(); + missing.addAll(set2); + missing.removeAll(set1); + + Set excess = new HashSet(); + excess.addAll(set1); + excess.removeAll(set2); + + if (!missing.isEmpty()) { + fail("Missing elements in query result: " + missing); + } + + if (!excess.isEmpty()) { + fail("Excess elements in query result: " + excess); + } + } + + private static Set toSet(Iterator it) { + Set set = new HashSet(); + while (it.hasNext()) { + set.add(it.next()); + } + return set; + } + + +} Modified: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/user/UserImporterTest.java URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/user/UserImporterTest.java?rev=1031680&r1=1031679&r2=1031680&view=diff ============================================================================== --- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/user/UserImporterTest.java (original) +++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/security/user/UserImporterTest.java Fri Nov 5 17:53:57 2010 @@ -19,12 +19,7 @@ package org.apache.jackrabbit.core.secur import org.apache.jackrabbit.api.JackrabbitSession; import org.apache.jackrabbit.api.security.principal.PrincipalIterator; import org.apache.jackrabbit.api.security.principal.PrincipalManager; -import org.apache.jackrabbit.api.security.user.Authorizable; -import org.apache.jackrabbit.api.security.user.AuthorizableExistsException; -import org.apache.jackrabbit.api.security.user.Group; -import org.apache.jackrabbit.api.security.user.Impersonation; -import org.apache.jackrabbit.api.security.user.User; -import org.apache.jackrabbit.api.security.user.UserManager; +import org.apache.jackrabbit.api.security.user.*; import org.apache.jackrabbit.commons.xml.ParsingContentHandler; import org.apache.jackrabbit.core.NodeImpl; import org.apache.jackrabbit.core.SessionImpl; @@ -41,29 +36,7 @@ import org.apache.jackrabbit.test.NotExe import org.xml.sax.ContentHandler; import org.xml.sax.SAXException; -import javax.jcr.AccessDeniedException; -import javax.jcr.Credentials; -import javax.jcr.ImportUUIDBehavior; -import javax.jcr.InvalidItemStateException; -import javax.jcr.InvalidSerializedDataException; -import javax.jcr.Item; -import javax.jcr.ItemExistsException; -import javax.jcr.ItemNotFoundException; -import javax.jcr.LoginException; -import javax.jcr.NamespaceException; -import javax.jcr.Node; -import javax.jcr.NodeIterator; -import javax.jcr.PathNotFoundException; -import javax.jcr.Property; -import javax.jcr.PropertyType; -import javax.jcr.ReferentialIntegrityException; -import javax.jcr.Repository; -import javax.jcr.RepositoryException; -import javax.jcr.Session; -import javax.jcr.UnsupportedRepositoryOperationException; -import javax.jcr.Value; -import javax.jcr.ValueFactory; -import javax.jcr.Workspace; +import javax.jcr.*; import javax.jcr.lock.LockException; import javax.jcr.nodetype.ConstraintViolationException; import javax.jcr.nodetype.NoSuchNodeTypeException; @@ -71,19 +44,13 @@ import javax.jcr.retention.RetentionMana import javax.jcr.security.AccessControlManager; import javax.jcr.version.VersionException; import javax.security.auth.Subject; - import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.security.AccessControlException; import java.security.Principal; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; -import java.util.UUID; +import java.util.*; /** * UserImporterTest... @@ -1405,6 +1372,10 @@ public class UserImporterTest extends Ab return null; } + public Iterator findAuthorizables(Query query) throws RepositoryException { + return null; + } + public User createUser(String userID, String password) throws AuthorizableExistsException, RepositoryException { return null; } Added: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/iterator/Predicates.java URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/iterator/Predicates.java?rev=1031680&view=auto ============================================================================== --- jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/iterator/Predicates.java (added) +++ jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/iterator/Predicates.java Fri Nov 5 17:53:57 2010 @@ -0,0 +1,67 @@ +/* + * 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.spi.commons.iterator; + +/** + * Utility class containing pre defined {@link Predicate}s + */ +public final class Predicates { + + /** + * A predicate which is always true + */ + public static final Predicate TRUE = new Predicate() { + public boolean evaluate(Object arg) { + return true; + } + }; + + /** + * A predicate which is always false + */ + public static final Predicate FALSE = new Predicate() { + public boolean evaluate(Object arg) { + return true; + } + }; + + private Predicates() { + // no instances allowed + } + + /** + * A predicate which is always true + * @param + * @return + */ + @SuppressWarnings("unchecked") + public static Predicate TRUE() { + return TRUE; + } + + /** + * A predicate which is always false + * @param + * @return + */ + @SuppressWarnings("unchecked") + public static Predicate FALSE() { + return FALSE; + } + +}