You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by ju...@apache.org on 2010/11/29 13:24:49 UTC

svn commit: r1040084 [2/2] - in /jackrabbit/branches/2.2: ./ jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/db/ jackrabbit-core/src/main/java/org/apache/jackrabbit/core/nodetype/ jackrabbit-core/src/main/java/org/apache/jackrabbit/core/p...

Modified: jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/join/QueryEngine.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/join/QueryEngine.java?rev=1040084&r1=1040083&r2=1040084&view=diff
==============================================================================
--- jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/join/QueryEngine.java (original)
+++ jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/join/QueryEngine.java Mon Nov 29 12:24:48 2010
@@ -16,68 +16,45 @@
  */
 package org.apache.jackrabbit.core.query.lucene.join;
 
-import static javax.jcr.query.qom.QueryObjectModelConstants.JCR_OPERATOR_EQUAL_TO;
-import static javax.jcr.query.qom.QueryObjectModelConstants.JCR_OPERATOR_GREATER_THAN;
-import static javax.jcr.query.qom.QueryObjectModelConstants.JCR_OPERATOR_GREATER_THAN_OR_EQUAL_TO;
-import static javax.jcr.query.qom.QueryObjectModelConstants.JCR_OPERATOR_LESS_THAN;
-import static javax.jcr.query.qom.QueryObjectModelConstants.JCR_OPERATOR_LESS_THAN_OR_EQUAL_TO;
-import static javax.jcr.query.qom.QueryObjectModelConstants.JCR_OPERATOR_LIKE;
-import static javax.jcr.query.qom.QueryObjectModelConstants.JCR_OPERATOR_NOT_EQUAL_TO;
+import static javax.jcr.query.qom.QueryObjectModelConstants.JCR_JOIN_TYPE_LEFT_OUTER;
+import static javax.jcr.query.qom.QueryObjectModelConstants.JCR_JOIN_TYPE_RIGHT_OUTER;
 import static javax.jcr.query.qom.QueryObjectModelConstants.JCR_ORDER_DESCENDING;
 
+import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.LinkedHashMap;
 import java.util.List;
-import java.util.Locale;
 import java.util.Map;
 
-import javax.jcr.Node;
-import javax.jcr.NodeIterator;
-import javax.jcr.PropertyType;
-import javax.jcr.RangeIterator;
 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.nodetype.NoSuchNodeTypeException;
 import javax.jcr.nodetype.NodeType;
 import javax.jcr.nodetype.NodeTypeManager;
 import javax.jcr.nodetype.PropertyDefinition;
-import javax.jcr.query.Query;
-import javax.jcr.query.QueryManager;
+import javax.jcr.query.InvalidQueryException;
 import javax.jcr.query.QueryResult;
 import javax.jcr.query.Row;
 import javax.jcr.query.RowIterator;
-import javax.jcr.query.qom.And;
-import javax.jcr.query.qom.BindVariableValue;
-import javax.jcr.query.qom.ChildNode;
 import javax.jcr.query.qom.Column;
-import javax.jcr.query.qom.Comparison;
 import javax.jcr.query.qom.Constraint;
-import javax.jcr.query.qom.DescendantNode;
-import javax.jcr.query.qom.FullTextSearch;
 import javax.jcr.query.qom.Join;
-import javax.jcr.query.qom.Literal;
-import javax.jcr.query.qom.LowerCase;
-import javax.jcr.query.qom.Not;
 import javax.jcr.query.qom.Operand;
-import javax.jcr.query.qom.Or;
 import javax.jcr.query.qom.Ordering;
-import javax.jcr.query.qom.PropertyExistence;
 import javax.jcr.query.qom.PropertyValue;
 import javax.jcr.query.qom.QueryObjectModelFactory;
-import javax.jcr.query.qom.SameNode;
 import javax.jcr.query.qom.Selector;
 import javax.jcr.query.qom.Source;
-import javax.jcr.query.qom.UpperCase;
 
 import org.apache.jackrabbit.commons.JcrUtils;
-import org.apache.jackrabbit.commons.iterator.NodeIteratorAdapter;
-import org.apache.jackrabbit.commons.iterator.RangeIteratorAdapter;
 import org.apache.jackrabbit.commons.iterator.RowIteratorAdapter;
+import org.apache.jackrabbit.core.query.lucene.LuceneQueryFactory;
 
 public class QueryEngine {
 
@@ -128,7 +105,7 @@ public class QueryEngine {
 
     }
 
-    private final Session session;
+    private final LuceneQueryFactory lqf;
 
     private final NodeTypeManager ntManager;
 
@@ -138,9 +115,10 @@ public class QueryEngine {
 
     private final OperandEvaluator evaluator;
 
-    public QueryEngine(Session session, Map<String, Value> variables)
-            throws RepositoryException {
-        this.session = session;
+    public QueryEngine(
+            Session session, LuceneQueryFactory lqf,
+            Map<String, Value> variables) throws RepositoryException {
+        this.lqf = lqf;
 
         Workspace workspace = session.getWorkspace();
         this.ntManager = workspace.getNodeTypeManager();
@@ -160,6 +138,12 @@ public class QueryEngine {
                     columns, selector, constraint, orderings, offset, limit);
         } else if (source instanceof Join) {
             Join join = (Join) source;
+            if (join.getJoinType() == JCR_JOIN_TYPE_RIGHT_OUTER) {
+                // Swap the join sources to normalize all outer joins to left
+                join = qomFactory.join(
+                        join.getRight(), join.getLeft(),
+                        JCR_JOIN_TYPE_LEFT_OUTER, join.getJoinCondition());
+            }
             return execute(
                     columns, join, constraint, orderings, offset, limit);
         } else {
@@ -221,155 +205,29 @@ public class QueryEngine {
         return sort(result, orderings, offset, limit);
     }
 
-    private String toSqlConstraint(Constraint constraint)
-            throws RepositoryException {
-        if (constraint instanceof And) {
-            And and = (And) constraint;
-            String c1 = toSqlConstraint(and.getConstraint1());
-            String c2 = toSqlConstraint(and.getConstraint2());
-            return "(" + c1 + ") AND (" + c2 + ")";
-        } else if (constraint instanceof Or) {
-            Or or = (Or) constraint;
-            String c1 = toSqlConstraint(or.getConstraint1());
-            String c2 = toSqlConstraint(or.getConstraint2());
-            return "(" + c1 + ") OR (" + c2 + ")";
-        } else if (constraint instanceof Not) {
-            Not or = (Not) constraint;
-            return "NOT (" + toSqlConstraint(or.getConstraint()) + ")";
-        } else if (constraint instanceof Comparison) {
-            Comparison c = (Comparison) constraint;
-            String left = toSqlOperand(c.getOperand1());
-            String right = toSqlOperand(c.getOperand2());
-            if (c.getOperator().equals(JCR_OPERATOR_EQUAL_TO)) {
-                return left + " = " + right;
-            } else if (c.getOperator().equals(JCR_OPERATOR_GREATER_THAN)) {
-                return left + " > " + right;
-            } else if (c.getOperator().equals(JCR_OPERATOR_GREATER_THAN_OR_EQUAL_TO)) {
-                return left + " >= " + right;
-            } else if (c.getOperator().equals(JCR_OPERATOR_LESS_THAN)) {
-                return left + " < " + right;
-            } else if (c.getOperator().equals(JCR_OPERATOR_LESS_THAN_OR_EQUAL_TO)) {
-                return left + " <= " + right;
-            } else if (c.getOperator().equals(JCR_OPERATOR_LIKE)) {
-                return left + " LIKE " + right;
-            } else if (c.getOperator().equals(JCR_OPERATOR_NOT_EQUAL_TO)) {
-                return left + " <> " + right;
-            } else {
-                throw new RepositoryException("Unsupported comparison: " + c);
-            }
-        } else if (constraint instanceof SameNode) {
-            SameNode sn = (SameNode) constraint;
-            return "jcr:path = '" + sn.getPath() + "'";
-        } else if (constraint instanceof ChildNode) {
-            ChildNode cn = (ChildNode) constraint;
-            return "jcr:path LIKE '" + cn.getParentPath() + "/%'";
-        } else if (constraint instanceof DescendantNode) {
-            DescendantNode dn = (DescendantNode) constraint;
-            return "jcr:path LIKE '" + dn.getAncestorPath() + "/%'";
-        } else if (constraint instanceof PropertyExistence) {
-            PropertyExistence pe = (PropertyExistence) constraint;
-            return pe.getPropertyName() + " IS NOT NULL";
-        } else if (constraint instanceof FullTextSearch) {
-            FullTextSearch fts = (FullTextSearch) constraint;
-            String expr = toSqlOperand(fts.getFullTextSearchExpression());
-            return "CONTAINS(" + fts.getPropertyName() + ", " + expr + ")";
-        } else  {
-            throw new RepositoryException("Unsupported constraint: " + constraint);
-        }
-    }
-
-    private static enum Transform {
-        NONE,
-        UPPER,
-        LOWER
-    }
-
-    private String toSqlOperand(Operand operand) throws RepositoryException {
-        return toSqlOperand(operand, Transform.NONE);
-    }
-
-    private String toSqlOperand(Operand operand, Transform transform)
-            throws RepositoryException {
-        if (operand instanceof PropertyValue) {
-            PropertyValue pv = (PropertyValue) operand;
-            switch (transform) {
-            case UPPER:
-                return "UPPER(" + pv.getPropertyName() + ")";
-            case LOWER:
-                return "LOWER(" + pv.getPropertyName() + ")";
-            default:
-                return pv.getPropertyName();
-            } 
-        } else if (operand instanceof LowerCase) {
-            LowerCase lc = (LowerCase) operand;
-            if (transform == Transform.NONE) {
-                transform = Transform.LOWER;
-            }
-            return toSqlOperand(lc.getOperand(), transform);
-        } else if (operand instanceof UpperCase) {
-            UpperCase uc = (UpperCase) operand;
-            if (transform == Transform.NONE) {
-                transform = Transform.UPPER;
-            }
-            return toSqlOperand(uc.getOperand(), transform);
-        } else if ((operand instanceof Literal)
-                || (operand instanceof BindVariableValue)) {
-            Value value = evaluator.getValue(operand, null);
-            int type = value.getType();
-            if (type == PropertyType.LONG || type == PropertyType.DOUBLE) {
-                return value.getString();
-            } else if (type == PropertyType.DATE && transform == Transform.NONE) {
-                return "TIMESTAMP '" + value.getString() + "'";
-            } else if (transform == Transform.UPPER) {
-                return "'" + value.getString().toUpperCase(Locale.ENGLISH) + "'";
-            } else if (transform == Transform.LOWER) {
-                return "'" + value.getString().toLowerCase(Locale.ENGLISH) + "'";
-            } else {
-                return "'" + value.getString() + "'";
-            }
-        } else {
-            throw new RepositoryException("Uknown operand type: " + operand);
-        }
-    }
-
     protected QueryResult execute(
             Column[] columns, Selector selector, Constraint constraint,
             Ordering[] orderings, long offset, long limit)
             throws RepositoryException {
-        StringBuilder builder = new StringBuilder();
-        builder.append("SELECT * FROM ");
-        builder.append(selector.getNodeTypeName());
-        if (constraint != null) {
-            builder.append(" WHERE ");
-            builder.append(toSqlConstraint(constraint));
-        }
-
-        QueryManager manager = session.getWorkspace().getQueryManager();
-        Query query = manager.createQuery(builder.toString(), Query.SQL);
-
         Map<String, NodeType> selectorMap = getSelectorNames(selector);
-        final String[] selectorNames =
+        String[] selectorNames =
             selectorMap.keySet().toArray(new String[selectorMap.size()]);
 
-        final Map<String, PropertyValue> columnMap =
+        Map<String, PropertyValue> columnMap =
             getColumnMap(columns, selectorMap);
-        final String[] columnNames =
+        String[] columnNames =
             columnMap.keySet().toArray(new String[columnMap.size()]);
 
-        NodeIterator nodes = query.execute().getNodes();
-        final String selectorName = selector.getSelectorName();
-        RowIterator rows = new RowIteratorAdapter(nodes) {
-            @Override
-            public Object next() {
-                Node node = (Node) super.next();
-                return new SelectorRow(
-                        columnMap, evaluator, selectorName, node, 1.0);
-            }
-        };
-
-        QueryResult result =
-            new SimpleQueryResult(columnNames, selectorNames, rows);
-        return sort(result, orderings, offset, limit);
+        try {
+            RowIterator rows = new RowIteratorAdapter(lqf.execute(
+                    columnMap, selector, constraint));
+            QueryResult result =
+                new SimpleQueryResult(columnNames, selectorNames, rows);
+            return sort(result, orderings, offset, limit);
+        } catch (IOException e) {
+            throw new RepositoryException(
+                    "Failed to access the query index", e);
+        }
     }
 
     private Map<String, PropertyValue> getColumnMap(
@@ -418,8 +276,7 @@ public class QueryEngine {
         if (source instanceof Selector) {
             Selector selector = (Selector) source;
             return Collections.singletonMap(
-                    selector.getSelectorName(),
-                    ntManager.getNodeType(selector.getNodeTypeName()));
+                    selector.getSelectorName(), getNodeType(selector));
         } else if (source instanceof Join) {
             Join join = (Join) source;
             Map<String, NodeType> map = new LinkedHashMap<String, NodeType>();
@@ -432,6 +289,15 @@ public class QueryEngine {
         }
     }
 
+    private NodeType getNodeType(Selector selector) throws RepositoryException {
+        try {
+            return ntManager.getNodeType(selector.getNodeTypeName());
+        } catch (NoSuchNodeTypeException e) {
+            throw new InvalidQueryException(
+                    "Selected node type does not exist: " + selector, e);
+        }
+    }
+
     /**
      * Sorts the given query results according to the given QOM orderings.
      * If one or more orderings have been specified, this method will iterate
@@ -461,13 +327,13 @@ public class QueryEngine {
                 Collections.sort(rows, new RowComparator(orderings));
             }
 
-            if (offset != 0 || limit >= 0) {
-                int from = (int) offset;
-                int to = rows.size();
-                if (limit >= 0 && offset + limit < to) {
-                    to = (int) (offset + limit);
-                }
-                rows = rows.subList(from, to);
+            if (offset > 0) {
+                int size = rows.size();
+                rows = rows.subList((int) Math.min(offset, size), size);
+            }
+            if (limit >= 0) {
+                int size = rows.size();
+                rows = rows.subList(0, (int) Math.min(limit, size));
             }
 
             return new SimpleQueryResult(

Modified: jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/join/SameNodeJoinMerger.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/join/SameNodeJoinMerger.java?rev=1040084&r1=1040083&r2=1040084&view=diff
==============================================================================
--- jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/join/SameNodeJoinMerger.java (original)
+++ jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/join/SameNodeJoinMerger.java Mon Nov 29 12:24:48 2010
@@ -33,6 +33,8 @@ import javax.jcr.query.qom.PropertyValue
 import javax.jcr.query.qom.QueryObjectModelFactory;
 import javax.jcr.query.qom.SameNodeJoinCondition;
 
+import org.apache.jackrabbit.spi.commons.conversion.PathResolver;
+
 class SameNodeJoinMerger extends JoinMerger {
 
     private final String selector1;
@@ -91,10 +93,14 @@ class SameNodeJoinMerger extends JoinMer
             Node node = row.getNode(selector2);
             if (node != null) {
                 try {
-                    if (path != null) {
-                        node = node.getNode(path);
+                    String p = node.getPath();
+                    if (path != null && !".".equals(path)) {
+                        if (!"/".equals(p)) {
+                            p += "/";
+                        }
+                        p += path;
                     }
-                    return Collections.singleton(node.getPath());
+                    return Collections.singleton(p);
                 } catch (PathNotFoundException e) {
                     // fall through
                 }

Modified: jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/join/ValueComparator.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/join/ValueComparator.java?rev=1040084&r1=1040083&r2=1040084&view=diff
==============================================================================
--- jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/join/ValueComparator.java (original)
+++ jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/join/ValueComparator.java Mon Nov 29 12:24:48 2010
@@ -26,12 +26,16 @@ import static javax.jcr.query.qom.QueryO
 import static javax.jcr.query.qom.QueryObjectModelConstants.JCR_OPERATOR_LESS_THAN;
 import static javax.jcr.query.qom.QueryObjectModelConstants.JCR_OPERATOR_LESS_THAN_OR_EQUAL_TO;
 import static javax.jcr.query.qom.QueryObjectModelConstants.JCR_OPERATOR_LIKE;
+import static javax.jcr.query.qom.QueryObjectModelConstants.JCR_OPERATOR_NOT_EQUAL_TO;
 
 import java.util.Comparator;
+import java.util.regex.Pattern;
 
 import javax.jcr.RepositoryException;
 import javax.jcr.Value;
 
+import org.apache.jackrabbit.core.query.lucene.Util;
+
 /**
  * Comparator for {@link Value} instances.
  */
@@ -78,10 +82,16 @@ public class ValueComparator implements 
             return compare(a, b) < 0;
         } else if (JCR_OPERATOR_LESS_THAN_OR_EQUAL_TO.equals(operator)) {
             return compare(a, b) <= 0;
+        } else if (JCR_OPERATOR_NOT_EQUAL_TO.equals(operator)) {
+            return compare(a, b) != 0;
         } else if (JCR_OPERATOR_LIKE.equals(operator)) {
-            // TODO: Implement LIKE support
-            throw new RuntimeException(
-                    "LIKE comparisions are not currently supported");
+            try {
+                Pattern pattern = Util.createRegexp(b.getString());
+                return pattern.matcher(a.getString()).matches();
+            } catch (RepositoryException e) {
+                throw new RuntimeException(
+                        "Unable to compare values " + a + " and " + b, e);
+            }
         } else {
             throw new IllegalArgumentException(
                     "Unknown comparison operator: " + operator);

Modified: jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/SharedItemStateManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/SharedItemStateManager.java?rev=1040084&r1=1040083&r2=1040084&view=diff
==============================================================================
--- jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/SharedItemStateManager.java (original)
+++ jackrabbit/branches/2.2/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/state/SharedItemStateManager.java Mon Nov 29 12:24:48 2010
@@ -17,6 +17,7 @@
 package org.apache.jackrabbit.core.state;
 
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Set;
@@ -1693,33 +1694,64 @@ public class SharedItemStateManager
     }
 
     /**
+     * Identifiers of the item states that are currently being loaded from
+     * the underlying persistence manager. Used exclusively by the
+     * {@link #getNonVirtualItemState(ItemId)} method to prevent two threads
+     * from concurrently loading the same items.
+     */
+    private final Set<ItemId> currentlyLoading = new HashSet<ItemId>();
+
+    /**
      * Returns the item state for the given id without considering virtual
      * item state providers.
      */
     private ItemState getNonVirtualItemState(ItemId id)
             throws NoSuchItemStateException, ItemStateException {
+        // First check if the item state is already in the cache
         ItemState state = cache.retrieve(id);
-        if (state == null) {
-            // not found in cache, load from persistent storage
+        if (state != null) {
+            return state;
+        }
+
+        // Wait if another thread is already loading this item state
+        synchronized (this) {
+            while (currentlyLoading.contains(id)) {
+                try {
+                    wait();
+                } catch (InterruptedException e) {
+                    throw new ItemStateException(
+                            "Interrupted while waiting for " + id, e);
+                }
+            }
+
+            state = cache.retrieve(id);
+            if (state != null) {
+                return state;
+            }
+
+            // No other thread has loaded the item state, so we'll do it
+            currentlyLoading.add(id);
+        }
+
+        try {
+            // Load the item state from persistent storage
+            // NOTE: This needs to happen outside a synchronized block!
             state = loadItemState(id);
             state.setStatus(ItemState.STATUS_EXISTING);
+            state.setContainer(this);
+
+            // put it in cache
+            cache.cache(state);
+
+            return state;
+        } finally {
+            // Notify other concurrent threads that we're done with this item
+            // NOTE: This needs to happen within the finally block!
             synchronized (this) {
-                // Use a double check to ensure that the cache entry is
-                // not created twice. We don't synchronize the entire
-                // method to allow the first cache retrieval to proceed
-                // even when another thread is loading a new item state.
-                ItemState cachedState = cache.retrieve(id);
-                if (cachedState == null) {
-                    // put it in cache
-                    cache.cache(state);
-                    // set parent container
-                    state.setContainer(this);
-                } else {
-                    state = cachedState;
-                }
+                currentlyLoading.remove(id);
+                notifyAll();
             }
         }
-        return state;
     }
 
     /**

Modified: jackrabbit/branches/2.2/jackrabbit-jca/src/main/java/org/apache/jackrabbit/jca/JCAManagedConnection.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.2/jackrabbit-jca/src/main/java/org/apache/jackrabbit/jca/JCAManagedConnection.java?rev=1040084&r1=1040083&r2=1040084&view=diff
==============================================================================
--- jackrabbit/branches/2.2/jackrabbit-jca/src/main/java/org/apache/jackrabbit/jca/JCAManagedConnection.java (original)
+++ jackrabbit/branches/2.2/jackrabbit-jca/src/main/java/org/apache/jackrabbit/jca/JCAManagedConnection.java Mon Nov 29 12:24:48 2010
@@ -52,7 +52,7 @@ public final class JCAManagedConnection
     /**
      * Session instance.
      */
-    private final Session session;
+    private Session session;
 
     /**
      * XAResource instance.
@@ -78,11 +78,11 @@ public final class JCAManagedConnection
      * Construct the managed connection.
      */
     public JCAManagedConnection(
-            JCAManagedConnectionFactory mcf, JCAConnectionRequestInfo cri,
-            Session session) {
+            JCAManagedConnectionFactory mcf, JCAConnectionRequestInfo cri)
+            throws ResourceException {
         this.mcf = mcf;
         this.cri = cri;
-        this.session = session;
+        this.session = openSession();
         this.listeners = new LinkedList<ConnectionEventListener>();
         this.handles = new LinkedList<JCASessionHandle>();
         if (this.mcf.getBindSessionToTransaction().booleanValue()) {
@@ -93,10 +93,22 @@ public final class JCAManagedConnection
     }
 
     /**
-     * Return the repository.
+     * Create a new session.
      */
-    private Repository getRepository() {
-        return mcf.getRepository();
+    @SuppressWarnings("deprecation")
+    private Session openSession() throws ResourceException {
+        try {
+            Session session = mcf.getRepository().login(
+                    cri.getCredentials(), cri.getWorkspace());
+            log("Created session (" + session + ")");
+            return session;
+        } catch (RepositoryException e) {
+            log("Failed to create session", e);
+            ResourceException exception = new ResourceException(
+                    "Failed to create session: " + e.getMessage());
+            exception.setLinkedException(e);
+            throw exception;
+        }
     }
 
     /**
@@ -155,14 +167,8 @@ public final class JCAManagedConnection
     public void cleanup()
             throws ResourceException {
         synchronized (handles) {
-            try {
-                this.session.refresh(false);
-            } catch (RepositoryException e) {
-                ResourceException exception =
-                    new ResourceException("unable to cleanup connection");
-                exception.setLinkedException(e);
-                throw exception;
-            }
+            this.session.logout();
+            this.session = openSession();
             this.handles.clear();
         }
     }
@@ -229,20 +235,31 @@ public final class JCAManagedConnection
         }
     }
 
+    @SuppressWarnings("deprecation")
+    private String getDescriptor(String key) throws ResourceException {
+        try {
+            return mcf.getRepository().getDescriptor(key);
+        } catch (RepositoryException e) {
+            log("Failed to access the repository", e);
+            ResourceException exception = new ResourceException(
+                    "Failed to access the repository: " + e.getMessage());
+            exception.setLinkedException(e);
+            throw exception;
+        }
+    }
+
     /**
      * Return the product name.
      */
-    public String getEISProductName()
-            throws ResourceException {
-        return getRepository().getDescriptor(Repository.REP_NAME_DESC);
+    public String getEISProductName() throws ResourceException {
+        return getDescriptor(Repository.REP_NAME_DESC);
     }
 
     /**
      * Return the product version.
      */
-    public String getEISProductVersion()
-            throws ResourceException {
-        return getRepository().getDescriptor(Repository.REP_VERSION_DESC);
+    public String getEISProductVersion() throws ResourceException {
+        return getDescriptor(Repository.REP_VERSION_DESC);
     }
 
     /**

Modified: jackrabbit/branches/2.2/jackrabbit-jca/src/main/java/org/apache/jackrabbit/jca/JCAManagedConnectionFactory.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.2/jackrabbit-jca/src/main/java/org/apache/jackrabbit/jca/JCAManagedConnectionFactory.java?rev=1040084&r1=1040083&r2=1040084&view=diff
==============================================================================
--- jackrabbit/branches/2.2/jackrabbit-jca/src/main/java/org/apache/jackrabbit/jca/JCAManagedConnectionFactory.java (original)
+++ jackrabbit/branches/2.2/jackrabbit-jca/src/main/java/org/apache/jackrabbit/jca/JCAManagedConnectionFactory.java Mon Nov 29 12:24:48 2010
@@ -21,10 +21,8 @@ import java.util.HashMap;
 import java.util.Map;
 import java.util.Set;
 
-import javax.jcr.Credentials;
 import javax.jcr.Repository;
 import javax.jcr.RepositoryException;
-import javax.jcr.Session;
 import javax.resource.ResourceException;
 import javax.resource.spi.ConnectionManager;
 import javax.resource.spi.ConnectionRequestInfo;
@@ -32,7 +30,6 @@ import javax.resource.spi.ManagedConnect
 import javax.resource.spi.ManagedConnectionFactory;
 import javax.security.auth.Subject;
 
-import org.apache.jackrabbit.api.XASession;
 import org.apache.jackrabbit.commons.JcrUtils;
 
 /**
@@ -134,35 +131,12 @@ public final class JCAManagedConnectionF
      */
     public Object createConnectionFactory(ConnectionManager cm)
             throws ResourceException {
-        createRepository();
         JCARepositoryHandle handle = new JCARepositoryHandle(this, cm);
         log("Created repository handle (" + handle + ")");
         return handle;
     }
 
     /**
-     * Create a new session.
-     */
-    private Session openSession(JCAConnectionRequestInfo cri)
-            throws ResourceException {
-        createRepository();
-        Credentials creds = cri.getCredentials();
-        String workspace = cri.getWorkspace();
-
-        try {
-            Session session = getRepository().login(creds, workspace);
-            log("Created session (" + session + ")");
-            return session;
-        } catch (RepositoryException e) {
-            log("Failed to create session", e);
-            ResourceException exception = new ResourceException(
-                    "Failed to create session: " + e.getMessage());
-            exception.setLinkedException(e);
-            throw exception;
-        }
-    }
-
-    /**
      * {@inheritDoc}
      * <p/>
      * Creates a new physical connection to the underlying EIS resource manager.
@@ -186,13 +160,12 @@ public final class JCAManagedConnectionF
      */
     private ManagedConnection createManagedConnection(JCAConnectionRequestInfo cri)
             throws ResourceException {
-        return new JCAManagedConnection(this, cri, openSession(cri));
+        return new JCAManagedConnection(this, cri);
     }
 
     /**
      * Returns a matched connection from the candidate set of connections.
      */
-    @SuppressWarnings("unchecked")
     public ManagedConnection matchManagedConnections(
             Set set, Subject subject, ConnectionRequestInfo cri)
             throws ResourceException {
@@ -212,9 +185,14 @@ public final class JCAManagedConnectionF
     }
 
     /**
-     * Return the repository.
+     * Return the repository, automatically creating it if needed.
      */
-    public Repository getRepository() {
+    public synchronized Repository getRepository() throws RepositoryException {
+        if (repository == null) {
+            JCARepositoryManager mgr = JCARepositoryManager.getInstance();
+            repository = mgr.createRepository(parameters);
+            log("Created repository (" + repository + ")");
+        }
         return repository;
     }
 
@@ -266,26 +244,6 @@ public final class JCAManagedConnectionF
     }
 
     /**
-     * Create repository.
-     */
-    private void createRepository()
-            throws ResourceException {
-        if (repository == null) {
-            try {
-                JCARepositoryManager mgr = JCARepositoryManager.getInstance();
-                repository = mgr.createRepository(parameters);
-                log("Created repository (" + repository + ")");
-            } catch (RepositoryException e) {
-                log("Failed to create repository", e);
-                ResourceException exception = new ResourceException(
-                        "Failed to create session: " + e.getMessage());
-                exception.setLinkedException(e);
-                throw exception;
-            }
-        }
-    }
-
-    /**
      * Shutdown the repository.
      */
     protected void finalize() {

Modified: jackrabbit/branches/2.2/jackrabbit-jca/src/main/java/org/apache/jackrabbit/jca/JCARepositoryHandle.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.2/jackrabbit-jca/src/main/java/org/apache/jackrabbit/jca/JCARepositoryHandle.java?rev=1040084&r1=1040083&r2=1040084&view=diff
==============================================================================
--- jackrabbit/branches/2.2/jackrabbit-jca/src/main/java/org/apache/jackrabbit/jca/JCARepositoryHandle.java (original)
+++ jackrabbit/branches/2.2/jackrabbit-jca/src/main/java/org/apache/jackrabbit/jca/JCARepositoryHandle.java Mon Nov 29 12:24:48 2010
@@ -66,6 +66,7 @@ public final class JCARepositoryHandle e
     /**
      * Creates a new session.
      */
+    @SuppressWarnings("deprecation")
     public Session login(Credentials creds, String workspace)
             throws RepositoryException {
         try {
@@ -113,7 +114,7 @@ public final class JCARepositoryHandle e
             this.mcf = mcf;
         }
 
-        public Repository getRepository() {
+        public Repository getRepository() throws RepositoryException {
             return mcf.getRepository();
         }
 

Modified: jackrabbit/branches/2.2/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/webdav/QueryUtil.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.2/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/webdav/QueryUtil.java?rev=1040084&r1=1040083&r2=1040084&view=diff
==============================================================================
--- jackrabbit/branches/2.2/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/webdav/QueryUtil.java (original)
+++ jackrabbit/branches/2.2/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/webdav/QueryUtil.java Mon Nov 29 12:24:48 2010
@@ -65,14 +65,15 @@ public class QueryUtil implements JcrRem
         columnNames.add(XMLUtil.getChildText(columnElement, JCR_NAME_LN, NS_URI));
         selectorNames.add(XMLUtil.getChildText(columnElement, JCR_SELECTOR_NAME_LN, NS_URI));
 
-        Value jcrValue;
+        Value jcrValue = null;
         Element valueElement = XMLUtil.getChildElement(columnElement, JCR_VALUE_LN, NS_URI);
         if (valueElement != null) {
-            String typeStr = XMLUtil.getAttribute(valueElement, ATTR_VALUE_TYPE, NS_URI);
-            jcrValue = ValueHelper.deserialize(XMLUtil.getText(valueElement),
-                    PropertyType.valueFromName(typeStr), true, valueFactory);
-        } else {
-            jcrValue = null;
+            String text = XMLUtil.getText(valueElement);
+            if (text != null) {
+                String typeStr = XMLUtil.getAttribute(valueElement, ATTR_VALUE_TYPE, NS_URI);
+                jcrValue = ValueHelper.deserialize(
+                        text, PropertyType.valueFromName(typeStr), true, valueFactory);
+            }
         }
         values.add(jcrValue);
     }

Modified: jackrabbit/branches/2.2/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/util/Base64.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.2/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/util/Base64.java?rev=1040084&r1=1040083&r2=1040084&view=diff
==============================================================================
--- jackrabbit/branches/2.2/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/util/Base64.java (original)
+++ jackrabbit/branches/2.2/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/util/Base64.java Mon Nov 29 12:24:48 2010
@@ -278,7 +278,7 @@ public class Base64 {
                     }
                     posChunk = 0;
                 }
-            } else {
+            } else if (!Character.isWhitespace(c)) {
                 throw new IllegalArgumentException("specified data is not base64 encoded");
             }
         }

Modified: jackrabbit/branches/2.2/jackrabbit-jcr-commons/src/test/java/org/apache/jackrabbit/util/Base64Test.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.2/jackrabbit-jcr-commons/src/test/java/org/apache/jackrabbit/util/Base64Test.java?rev=1040084&r1=1040083&r2=1040084&view=diff
==============================================================================
--- jackrabbit/branches/2.2/jackrabbit-jcr-commons/src/test/java/org/apache/jackrabbit/util/Base64Test.java (original)
+++ jackrabbit/branches/2.2/jackrabbit-jcr-commons/src/test/java/org/apache/jackrabbit/util/Base64Test.java Mon Nov 29 12:24:48 2010
@@ -39,6 +39,16 @@ public class Base64Test extends TestCase
     }
 
     /**
+     * Tests that whitespace characters are ignored within base64 data.
+     */
+    public void testWhitespace() throws Exception {
+        ByteArrayOutputStream buffer = new ByteArrayOutputStream();
+        Base64.decode(" d G\tV \tzdA\n= =\n", buffer);
+        byte[] data = buffer.toByteArray();
+        assertEquals("test", new String(data, "US-ASCII"));
+    }
+
+    /**
      * Tests that base 64 encoding/decoding round trips are lossless.
      */
     public void testBase64() throws Exception {

Propchange: jackrabbit/branches/2.2/jackrabbit-jcr-servlet/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Mon Nov 29 12:24:48 2010
@@ -0,0 +1 @@
+/jackrabbit/trunk/jackrabbit-jcr-servlet:1038201,1038203,1038205,1038657,1039064,1039347,1039408,1039422-1039423,1039888,1039946,1040033

Modified: jackrabbit/branches/2.2/jackrabbit-webapp/src/main/webapp/search.jsp
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.2/jackrabbit-webapp/src/main/webapp/search.jsp?rev=1040084&r1=1040083&r2=1040084&view=diff
==============================================================================
--- jackrabbit/branches/2.2/jackrabbit-webapp/src/main/webapp/search.jsp (original)
+++ jackrabbit/branches/2.2/jackrabbit-webapp/src/main/webapp/search.jsp Mon Nov 29 12:24:48 2010
@@ -69,6 +69,7 @@
             String stmt;
             if (q.startsWith("related:")) {
                 String path = q.substring("related:".length());
+                path = path.replaceAll("'", "''");
                 stmt = "//element(*, nt:file)[rep:similar(jcr:content, '" + path + "/jcr:content')]/rep:excerpt(.) order by @jcr:score descending";
                 queryTerms = "similar to <b>" + Text.encodeIllegalXMLCharacters(path) + "</b>";
             } else {

Propchange: jackrabbit/branches/2.2/test/compatibility/create11/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Mon Nov 29 12:24:48 2010
@@ -0,0 +1 @@
+/jackrabbit/trunk/test/compatibility/create11:1038201,1038203,1038205,1038657,1039064,1039347,1039408,1039422-1039423,1039888,1039946,1040033

Propchange: jackrabbit/branches/2.2/test/compatibility/create12/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Mon Nov 29 12:24:48 2010
@@ -0,0 +1 @@
+/jackrabbit/trunk/test/compatibility/create12:1038201,1038203,1038205,1038657,1039064,1039347,1039408,1039422-1039423,1039888,1039946,1040033

Propchange: jackrabbit/branches/2.2/test/compatibility/create13/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Mon Nov 29 12:24:48 2010
@@ -0,0 +1 @@
+/jackrabbit/trunk/test/compatibility/create13:1038201,1038203,1038205,1038657,1039064,1039347,1039408,1039422-1039423,1039888,1039946,1040033

Propchange: jackrabbit/branches/2.2/test/compatibility/create14/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Mon Nov 29 12:24:48 2010
@@ -0,0 +1 @@
+/jackrabbit/trunk/test/compatibility/create14:1038201,1038203,1038205,1038657,1039064,1039347,1039408,1039422-1039423,1039888,1039946,1040033

Propchange: jackrabbit/branches/2.2/test/compatibility/create15/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Mon Nov 29 12:24:48 2010
@@ -0,0 +1 @@
+/jackrabbit/trunk/test/compatibility/create15:1038201,1038203,1038205,1038657,1039064,1039347,1039408,1039422-1039423,1039888,1039946,1040033

Propchange: jackrabbit/branches/2.2/test/compatibility/create16/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Mon Nov 29 12:24:48 2010
@@ -0,0 +1 @@
+/jackrabbit/trunk/test/compatibility/create16:1038201,1038203,1038205,1038657,1039064,1039347,1039408,1039422-1039423,1039888,1039946,1040033

Propchange: jackrabbit/branches/2.2/test/compatibility/create20/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Mon Nov 29 12:24:48 2010
@@ -0,0 +1 @@
+/jackrabbit/trunk/test/compatibility/create20:1038201,1038203,1038205,1038657,1039064,1039347,1039408,1039422-1039423,1039888,1039946,1040033

Propchange: jackrabbit/branches/2.2/test/compatibility/create21/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Mon Nov 29 12:24:48 2010
@@ -0,0 +1 @@
+/jackrabbit/trunk/test/compatibility/create21:1038201,1038203,1038205,1038657,1039064,1039347,1039408,1039422-1039423,1039888,1039946,1040033

Modified: jackrabbit/branches/2.2/test/performance/parent/pom.xml
URL: http://svn.apache.org/viewvc/jackrabbit/branches/2.2/test/performance/parent/pom.xml?rev=1040084&r1=1040083&r2=1040084&view=diff
==============================================================================
--- jackrabbit/branches/2.2/test/performance/parent/pom.xml (original)
+++ jackrabbit/branches/2.2/test/performance/parent/pom.xml Mon Nov 29 12:24:48 2010
@@ -58,6 +58,7 @@
         <plugin>
           <artifactId>maven-surefire-plugin</artifactId>
           <configuration>
+			<argLine>-Xms256m -Xmx512m</argLine>
             <enableAssertions>false</enableAssertions>
             <systemProperties>
               <property>
@@ -97,7 +98,7 @@
             <plugin>
               <artifactId>maven-surefire-plugin</artifactId>
               <configuration>
-                <argLine>-agentlib:${agentlib}</argLine>
+				<argLine>-Xmx512m -XX:MaxPermSize=512m -agentlib:${agentlib}</argLine>
               </configuration>
             </plugin>
           </plugins>