/*
* eXist Open Source Native XML Database
* Copyright (C) 2001-07 The eXist Project
* http://exist-db.org
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
* $Id$
*/
package org.exist.versioning;
import org.exist.security.PermissionDeniedException;
import org.exist.security.xacml.AccessContext;
import org.exist.source.StringSource;
import org.exist.storage.DBBroker;
import org.exist.storage.XQueryPool;
import org.exist.xmldb.XmldbURI;
import org.exist.xquery.CompiledXQuery;
import org.exist.xquery.XPathException;
import org.exist.xquery.XQuery;
import org.exist.xquery.XQueryContext;
import org.exist.xquery.value.IntegerValue;
import org.exist.xquery.value.Sequence;
import java.io.IOException;
public class VersioningHelper {
private final static String GET_CURRENT_REV =
"declare namespace v=\"http://exist-db.org/versioning\";\n" +
"declare variable $collection external;\n" +
"declare variable $document external;\n" +
"max(" +
" for $r in collection($collection)//v:properties[v:document = $document]/v:revision\n" +
" return xs:long($r)" +
")";
private final static StringSource GET_CURRENT_REV_SOURCE = new StringSource(GET_CURRENT_REV);
private final static String GET_CONFLICTING_REV =
"declare namespace v=\"http://exist-db.org/versioning\";\n" +
"declare variable $collection external;\n" +
"declare variable $document external;\n" +
"declare variable $base external;\n" +
"declare variable $key external;\n" +
"collection($collection)//v:properties[v:document = $document]" +
" [v:revision > $base][v:key != $key]";
private final static StringSource GET_CONFLICTING_REV_SOURCE = new StringSource(GET_CONFLICTING_REV);
private final static String GET_BASE_REV_FOR_KEY =
"declare namespace v=\"http://exist-db.org/versioning\";\n" +
"declare variable $collection external;\n" +
"declare variable $document external;\n" +
"declare variable $base external;\n" +
"declare variable $key external;\n" +
"let $p := collection($collection)//v:properties[v:document = $document]\n" +
"let $withKey := for $r in $p[v:revision > $base][v:key = $key] " +
" order by $r/v:revision descending return $r\n" +
"return\n" +
" if ($withKey) then\n" +
" xs:long($withKey[1]/v:revision)\n" +
" else\n" +
" xs:long($p[v:revision = $base]/v:revision)";
private final static StringSource GET_BASE_REV_FOR_KEY_SOURCE = new StringSource(GET_BASE_REV_FOR_KEY);
public static long getCurrentRevision(DBBroker broker, XmldbURI docPath) throws XPathException, IOException, PermissionDeniedException {
String docName = docPath.lastSegment().toString();
XmldbURI collectionPath = docPath.removeLastSegment();
XmldbURI path = VersioningTrigger.VERSIONS_COLLECTION.append(collectionPath);
XQuery xquery = broker.getXQueryService();
XQueryPool pool = xquery.getXQueryPool();
XQueryContext context;
CompiledXQuery compiled = pool.borrowCompiledXQuery(broker, GET_CURRENT_REV_SOURCE);
if(compiled == null)
context = xquery.newContext(AccessContext.VALIDATION_INTERNAL);
else
context = compiled.getContext();
context.declareVariable("collection", path.toString());
context.declareVariable("document", docName);
if(compiled == null)
compiled = xquery.compile(context, GET_CURRENT_REV_SOURCE);
try {
Sequence s = xquery.execute(compiled, Sequence.EMPTY_SEQUENCE);
if (s.isEmpty())
return 0;
IntegerValue iv = (IntegerValue) s.itemAt(0);
return iv.getLong();
} finally {
pool.returnCompiledXQuery(GET_CURRENT_REV_SOURCE, compiled);
}
}
public static boolean newerRevisionExists(DBBroker broker, XmldbURI docPath, long baseRev, String key) throws XPathException, IOException, PermissionDeniedException {
String docName = docPath.lastSegment().toString();
XmldbURI collectionPath = docPath.removeLastSegment();
XmldbURI path = VersioningTrigger.VERSIONS_COLLECTION.append(collectionPath);
XQuery xquery = broker.getXQueryService();
XQueryPool pool = xquery.getXQueryPool();
XQueryContext context;
CompiledXQuery compiled = pool.borrowCompiledXQuery(broker, GET_CONFLICTING_REV_SOURCE);
if(compiled == null)
context = xquery.newContext(AccessContext.VALIDATION_INTERNAL);
else
context = compiled.getContext();
context.declareVariable("collection", path.toString());
context.declareVariable("document", docName);
context.declareVariable("base", new IntegerValue(baseRev));
context.declareVariable("key", key);
if(compiled == null)
compiled = xquery.compile(context, GET_CONFLICTING_REV_SOURCE);
try {
Sequence s = xquery.execute(compiled, Sequence.EMPTY_SEQUENCE);
return !s.isEmpty();
} finally {
pool.returnCompiledXQuery(GET_CONFLICTING_REV_SOURCE, compiled);
}
}
public static long getBaseRevision(DBBroker broker, XmldbURI docPath, long baseRev, String sessionKey) throws XPathException, IOException, PermissionDeniedException {
String docName = docPath.lastSegment().toString();
XmldbURI collectionPath = docPath.removeLastSegment();
XmldbURI path = VersioningTrigger.VERSIONS_COLLECTION.append(collectionPath);
XQuery xquery = broker.getXQueryService();
XQueryPool pool = xquery.getXQueryPool();
XQueryContext context;
CompiledXQuery compiled = pool.borrowCompiledXQuery(broker, GET_BASE_REV_FOR_KEY_SOURCE);
if(compiled == null)
context = xquery.newContext(AccessContext.VALIDATION_INTERNAL);
else
context = compiled.getContext();
context.declareVariable("collection", path.toString());
context.declareVariable("document", docName);
context.declareVariable("base", new IntegerValue(baseRev));
context.declareVariable("key", sessionKey);
if(compiled == null)
compiled = xquery.compile(context, GET_BASE_REV_FOR_KEY_SOURCE);
try {
Sequence s = xquery.execute(compiled, Sequence.EMPTY_SEQUENCE);
if (s.isEmpty())
return 0;
IntegerValue iv = (IntegerValue) s.itemAt(0);
return iv.getLong();
} finally {
pool.returnCompiledXQuery(GET_BASE_REV_FOR_KEY_SOURCE, compiled);
}
}
}