You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by md...@apache.org on 2010/11/12 16:23:45 UTC
svn commit: r1034419 - in /jackrabbit/trunk:
jackrabbit-api/src/main/java/org/apache/jackrabbit/api/security/user/
jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/
jackrabbit-core/src/test/java/org/apache/jackrabbit/api/security/...
Author: mduerig
Date: Fri Nov 12 15:23:45 2010
New Revision: 1034419
URL: http://svn.apache.org/viewvc?rev=1034419&view=rev
Log:
JCR-2800: Implement search facility for users and groups
added condition for matching user/principal name
work in progress
Modified:
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
Modified: 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=1034419&r1=1034418&r2=1034419&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-api/src/main/java/org/apache/jackrabbit/api/security/user/QueryBuilder.java (original)
+++ jackrabbit/trunk/jackrabbit-api/src/main/java/org/apache/jackrabbit/api/security/user/QueryBuilder.java Fri Nov 12 15:23:45 2010
@@ -104,6 +104,20 @@ public interface QueryBuilder<T> {
void setLimit(long offset, long maxCount);
/**
+ * Create a condition which holds iff the name of the {@link Authorizable}
+ * matches a <code>pattern</code>.
+ * The percent character Ô%Õ represents any string of zero or more characters and the
+ * underscore character Ô_Õ represents any single character. Any literal use of these characters
+ * and the backslash character Ô\Õ must be escaped with a backslash character.
+ * The pattern is matched against the {@link Authorizable#getID() id} and the
+ * {@link Authorizable#getPrincipal() principal}.
+ *
+ * @param pattern Pattern to match the property at <code>relPath</code> against
+ * @return A condition
+ */
+ T nameMatches(String pattern);
+
+ /**
* Create a condition which holds iff the node of an {@link Authorizable} has a
* property at <code>relPath</code> which is not equal to <code>value</code>.
* The format of the <code>relPath</code> argument is the same as in XPath:
Modified: 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=1034419&r1=1034418&r2=1034419&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/XPathQueryBuilder.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/XPathQueryBuilder.java Fri Nov 12 15:23:45 2010
@@ -59,6 +59,7 @@ public class XPathQueryBuilder implement
}
interface ConditionVisitor {
+ void visit(NodeCondition nodeCondition) throws RepositoryException;
void visit(PropertyCondition condition) throws RepositoryException;
void visit(ContainsCondition condition);
void visit(ImpersonationCondition condition);
@@ -149,6 +150,10 @@ public class XPathQueryBuilder implement
return new PropertyCondition(relPath, op, value);
}
+ public Condition nameMatches(String pattern) {
+ return new NodeCondition(pattern);
+ }
+
public Condition neq(String relPath, Value value) {
return new PropertyCondition(relPath, RelationOp.NE, value);
}
@@ -203,6 +208,22 @@ public class XPathQueryBuilder implement
//------------------------------------------< private >---
+ static class NodeCondition implements Condition {
+ private final String pattern;
+
+ public NodeCondition(String pattern) {
+ this.pattern = pattern;
+ }
+
+ public String getPattern() {
+ return pattern;
+ }
+
+ public void accept(ConditionVisitor visitor) throws RepositoryException {
+ visitor.visit(this);
+ }
+ }
+
static class PropertyCondition implements Condition {
private final String relPath;
private final RelationOp op;
Modified: 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=1034419&r1=1034418&r2=1034419&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/XPathQueryEvaluator.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/security/user/XPathQueryEvaluator.java Fri Nov 12 15:23:45 2010
@@ -29,6 +29,7 @@ import org.apache.jackrabbit.spi.commons
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.apache.jackrabbit.test.api.util.Text;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -118,6 +119,22 @@ public class XPathQueryEvaluator impleme
//------------------------------------------< ConditionVisitor >---
+ public void visit(XPathQueryBuilder.NodeCondition condition) throws RepositoryException {
+ String repPrincipal = session.getJCRName(UserConstants.P_PRINCIPAL_NAME);
+
+ xPath.append('(')
+ .append("jcr:like(")
+ .append(repPrincipal)
+ .append(",'")
+ .append(condition.getPattern())
+ .append("')")
+ .append(" or ")
+ .append("jcr:like(fn:name(.),'")
+ .append(escape(condition.getPattern()))
+ .append("')")
+ .append(')');
+ }
+
public void visit(XPathQueryBuilder.PropertyCondition condition) throws RepositoryException {
RelationOp relOp = condition.getOp();
if (relOp == RelationOp.EX) {
@@ -183,6 +200,37 @@ public class XPathQueryEvaluator impleme
//------------------------------------------< private >---
+ /**
+ * Escape <code>string</code> for matching in jcr escaped node names
+ * @param string string to escape
+ * @return escaped string
+ */
+ public static String escape(String string) {
+ StringBuilder result = new StringBuilder();
+
+ int k = 0;
+ int j;
+ do {
+ j = string.indexOf('%', k); // split on %
+ if (j < 0) {
+ // jcr escape trail
+ result.append(Text.escapeIllegalJcrChars(string.substring(k)));
+ }
+ else if (j > 0 && string.charAt(j - 1) == '\\') {
+ // literal occurrence of % -> jcr escape
+ result.append(Text.escapeIllegalJcrChars(string.substring(k, j) + '%'));
+ }
+ else {
+ // wildcard occurrence of % -> jcr escape all but %
+ result.append(Text.escapeIllegalJcrChars(string.substring(k, j))).append('%');
+ }
+
+ k = j + 1;
+ } while (j >= 0);
+
+ return result.toString();
+ }
+
private String getNtName(Class<? extends Authorizable> selector) throws RepositoryException {
if (User.class.isAssignableFrom(selector)) {
return session.getJCRName(UserConstants.NT_REP_USER);
Modified: 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=1034419&r1=1034418&r2=1034419&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/security/user/UserManagerSearchTest.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/security/user/UserManagerSearchTest.java Fri Nov 12 15:23:45 2010
@@ -23,6 +23,7 @@ import org.apache.jackrabbit.spi.commons
import javax.jcr.RepositoryException;
import javax.jcr.Value;
+import java.security.Principal;
import java.util.*;
public class UserManagerSearchTest extends AbstractUserTest {
@@ -69,10 +70,25 @@ public class UserManagerSearchTest exten
private final Set<Group> groups = new HashSet<Group>();
private final Set<Authorizable> authorizables = new HashSet<Authorizable>();
+ private final Set<Authorizable> systemDefined = new HashSet<Authorizable>();
+
@Override
public void setUp() throws Exception {
super.setUp();
+ // todo P_PRINCIPAL_NAME
+ Iterator<Authorizable> systemAuthorizables = userMgr.findAuthorizables("rep:principalName", null);
+ while (systemAuthorizables.hasNext()) {
+ Authorizable authorizable = systemAuthorizables.next();
+ if (authorizable.isGroup()) {
+ groups.add((Group) authorizable);
+ }
+ else {
+ users.add((User) authorizable);
+ }
+ systemDefined.add(authorizable);
+ }
+
// Create a zoo. Please excuse my ignorance in zoology ;-)
animals = createGroup("animals");
invertebrates = createGroup("invertebrates");
@@ -161,7 +177,9 @@ public class UserManagerSearchTest exten
@Override
public void tearDown() throws Exception {
for (Authorizable authorizable : authorizables) {
- authorizable.remove();
+ if (!systemDefined.contains(authorizable)) {
+ authorizable.remove();
+ }
}
authorizables.clear();
groups.clear();
@@ -179,7 +197,7 @@ public class UserManagerSearchTest exten
public <T> void build(QueryBuilder<T> builder) { /* any */ }
});
- assertContainsAll(result, authorizables.iterator());
+ assertSameElements(result, authorizables.iterator());
}
public void testSelector() throws RepositoryException {
@@ -196,13 +214,13 @@ public class UserManagerSearchTest exten
});
if (User.class.isAssignableFrom(s)) {
- assertContainsAll(result, users.iterator());
+ assertSameElements(result, users.iterator());
}
else if (Group.class.isAssignableFrom(s)) {
- assertContainsAll(result, groups.iterator());
+ assertSameElements(result, groups.iterator());
}
else {
- assertContainsAll(result, authorizables.iterator());
+ assertSameElements(result, authorizables.iterator());
}
}
}
@@ -291,6 +309,30 @@ public class UserManagerSearchTest exten
}
}
+ public void testNameMatch() throws RepositoryException {
+ Iterator<Authorizable> result = userMgr.findAuthorizables(new Query() {
+ public <T> void build(QueryBuilder<T> builder) {
+ builder.setCondition(builder.nameMatches("a%"));
+ }
+ });
+
+ Iterator<Authorizable> expected = Iterators.filterIterator(authorizables.iterator(), new Predicate<Authorizable>() {
+ public boolean evaluate(Authorizable authorizable) {
+ try {
+ String name = authorizable.getID();
+ Principal principal = authorizable.getPrincipal();
+ return name.startsWith("a") || principal != null && principal.getName().startsWith("a");
+ } catch (RepositoryException e) {
+ fail(e.getMessage());
+ }
+ return false;
+ }
+ });
+
+ assertTrue(result.hasNext());
+ assertSameElements(result, expected);
+ }
+
public void testFindProperty1() throws RepositoryException {
Iterator<Authorizable> result = userMgr.findAuthorizables(new Query() {
public <T> void build(QueryBuilder<T> builder) {
@@ -404,7 +446,7 @@ public class UserManagerSearchTest exten
}
else {
String value = food[0].getString();
- return value.length() > 0 && value.charAt(0) == 'm';
+ return value.startsWith("m");
}
} catch (RepositoryException e) {
fail(e.getMessage());
@@ -608,6 +650,8 @@ public class UserManagerSearchTest exten
public void testSetBound() throws RepositoryException {
List<User> sortedUsers = new ArrayList<User>(users);
+ sortedUsers.removeAll(systemDefined); // remove system defined users: no @weight
+
Comparator<? super User> comp = new Comparator<User>() {
public int compare(User user1, User user2) {
try {
@@ -688,15 +732,6 @@ public class UserManagerSearchTest exten
}
}
- private static <T> void assertContainsAll(Iterator<? extends T> it1, Iterator<? extends T> it2) {
- Set<? extends T> set1 = toSet(it1);
- Set<? extends T> set2 = toSet(it2);
- set2.removeAll(set1);
- if (!set2.isEmpty()) {
- fail("Missing elements in query result: " + set2);
- }
- }
-
private static <T> void assertSameElements(Iterator<? extends T> it1, Iterator<? extends T> it2) {
Set<? extends T> set1 = toSet(it1);
Set<? extends T> set2 = toSet(it2);