blob: 7b5b7a2fe0e1c6799deb691a29563d6559addbf5 [file] [log] [blame]
/*
* 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.ocm.manager.impl;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.jcr.InvalidItemStateException;
import javax.jcr.Item;
import javax.jcr.Node;
import javax.jcr.NodeIterator;
import javax.jcr.PathNotFoundException;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.UnsupportedRepositoryOperationException;
import javax.jcr.Workspace;
import javax.jcr.lock.LockException;
import javax.jcr.lock.LockManager;
import javax.jcr.nodetype.NoSuchNodeTypeException;
import javax.jcr.query.InvalidQueryException;
import javax.jcr.query.QueryResult;
import javax.jcr.version.VersionHistory;
import javax.jcr.version.VersionManager;
import org.apache.commons.lang.StringUtils;
import org.apache.jackrabbit.ocm.exception.IllegalUnlockException;
import org.apache.jackrabbit.ocm.exception.IncorrectPersistentClassException;
import org.apache.jackrabbit.ocm.exception.JcrMappingException;
import org.apache.jackrabbit.ocm.exception.LockedException;
import org.apache.jackrabbit.ocm.exception.ObjectContentManagerException;
import org.apache.jackrabbit.ocm.exception.VersionException;
import org.apache.jackrabbit.ocm.lock.Lock;
import org.apache.jackrabbit.ocm.manager.ManagerConstant;
import org.apache.jackrabbit.ocm.manager.ObjectContentManager;
import org.apache.jackrabbit.ocm.manager.atomictypeconverter.impl.DefaultAtomicTypeConverterProvider;
import org.apache.jackrabbit.ocm.manager.cache.ObjectCache;
import org.apache.jackrabbit.ocm.manager.cache.impl.RequestObjectCacheImpl;
import org.apache.jackrabbit.ocm.manager.objectconverter.ObjectConverter;
import org.apache.jackrabbit.ocm.manager.objectconverter.impl.ObjectConverterImpl;
import org.apache.jackrabbit.ocm.manager.objectconverter.impl.ProxyManagerImpl;
import org.apache.jackrabbit.ocm.mapper.Mapper;
import org.apache.jackrabbit.ocm.mapper.impl.digester.DigesterMapperImpl;
import org.apache.jackrabbit.ocm.mapper.model.ClassDescriptor;
import org.apache.jackrabbit.ocm.query.Filter;
import org.apache.jackrabbit.ocm.query.Query;
import org.apache.jackrabbit.ocm.query.QueryManager;
import org.apache.jackrabbit.ocm.query.impl.QueryManagerImpl;
import org.apache.jackrabbit.ocm.repository.NodeUtil;
import org.apache.jackrabbit.ocm.version.Version;
import org.apache.jackrabbit.ocm.version.VersionIterator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
*
* Default implementation for
* {@link org.apache.jackrabbit.ocm.manager.ObjectContentManager}
*
* @author Sandro Boehme
* @author <a href="mailto:christophe.lombart@sword-technologies.com">Lombart
* Christophe</a>
* @author Martin Koci
* @author <a href='mailto:the_mindstorm[at]evolva[dot]ro'>Alexandru Popescu</a>
*/
public class ObjectContentManagerImpl implements ObjectContentManager {
private final static Logger log = LoggerFactory.getLogger(ObjectContentManagerImpl.class);
protected Session session;
protected Mapper mapper;
protected QueryManager queryManager;
protected ObjectConverter objectConverter;
protected ObjectCache requestObjectCache;
/**
* Creates a new <code>ObjectContentManager</code> that uses the passed in
* <code>Mapper</code>, and a <code>Session</code>
*
* @param mapper
* the Mapper component
* @param session
* The JCR session
*/
public ObjectContentManagerImpl(Session session, Mapper mapper) {
try {
this.session = session;
this.mapper = mapper;
// Use default setting for the following dependencies
DefaultAtomicTypeConverterProvider converterProvider = new DefaultAtomicTypeConverterProvider();
Map atomicTypeConverters = converterProvider.getAtomicTypeConverters();
this.queryManager = new QueryManagerImpl(mapper, atomicTypeConverters, session.getValueFactory());
this.requestObjectCache = new RequestObjectCacheImpl();
this.objectConverter = new ObjectConverterImpl(mapper, converterProvider, new ProxyManagerImpl(), requestObjectCache);
} catch (RepositoryException e) {
throw new org.apache.jackrabbit.ocm.exception.RepositoryException("Impossible to instantiate the object content manager", e);
}
}
/**
* Creates a new <code>ObjectContentManager</code> based on a JCR session
* and some xml mapping files.
*
* @param session
* The JCR session
* @param xmlMappingFiles
* the JCR mapping files used mainly to create the
* <code>Mapper</code> component
*/
public ObjectContentManagerImpl(Session session, String[] xmlMappingFiles) {
try {
this.session = session;
this.mapper = new DigesterMapperImpl(xmlMappingFiles);
DefaultAtomicTypeConverterProvider converterProvider = new DefaultAtomicTypeConverterProvider();
Map atomicTypeConverters = converterProvider.getAtomicTypeConverters();
this.queryManager = new QueryManagerImpl(mapper, atomicTypeConverters, session.getValueFactory());
this.requestObjectCache = new RequestObjectCacheImpl();
this.objectConverter = new ObjectConverterImpl(mapper, converterProvider, new ProxyManagerImpl(), requestObjectCache);
} catch (RepositoryException e) {
throw new org.apache.jackrabbit.ocm.exception.RepositoryException("Impossible to instantiate the object content manager", e);
}
}
/**
* Creates a new <code>ObjectContentManager</code> based on a JCR session
* and some xml mapping files.
*
* @param session
* The JCR session
* @param xmlMappingFiles
* the JCR mapping files used mainly to create the
* <code>Mapper</code> component
*/
public ObjectContentManagerImpl(Session session, InputStream[] xmlMappingFiles) {
try {
this.session = session;
this.mapper = new DigesterMapperImpl(xmlMappingFiles);
DefaultAtomicTypeConverterProvider converterProvider = new DefaultAtomicTypeConverterProvider();
Map atomicTypeConverters = converterProvider.getAtomicTypeConverters();
this.queryManager = new QueryManagerImpl(mapper, atomicTypeConverters, session.getValueFactory());
this.requestObjectCache = new RequestObjectCacheImpl();
this.objectConverter = new ObjectConverterImpl(mapper, converterProvider, new ProxyManagerImpl(), requestObjectCache);
} catch (RepositoryException e) {
throw new org.apache.jackrabbit.ocm.exception.RepositoryException("Impossible to instantiate the object content manager", e);
}
}
/**
* Full constructor.
*
* @param mapper
* the Mapper component
* @param converter
* the <code>ObjectConverter</code> to be used internally
* @param queryManager
* the query manager to used
* @param session
* The JCR session
*/
public ObjectContentManagerImpl(Mapper mapper, ObjectConverter converter, QueryManager queryManager, ObjectCache requestObjectCache, Session session) {
this.mapper = mapper;
this.session = session;
this.objectConverter = converter;
this.queryManager = queryManager;
this.requestObjectCache = requestObjectCache;
}
/**
* Sets the <code>Mapper</code> used by this object content manager.
*
* @param mapper
* mapping solver
*/
public void setMapper(Mapper mapper) {
this.mapper = mapper;
}
/**
* Sets the <code>ObjectConverter</code> that is used internally by this
* object content manager.
*
* @param objectConverter
* the internal <code>ObjectConverter</code>
*/
public void setObjectConverter(ObjectConverter objectConverter) {
this.objectConverter = objectConverter;
}
/**
* Sets the <code>QueryManager</code> used by the object content manager.
*
* @param queryManager
* a <code>QueryManager</code>
*/
public void setQueryManager(QueryManager queryManager) {
this.queryManager = queryManager;
}
public void setRequestObjectCache(ObjectCache requestObjectCache) {
this.requestObjectCache = requestObjectCache;
}
/**
* @see org.apache.jackrabbit.ocm.manager.ObjectContentManager#getObject(java.lang.Class,
* java.lang.String)
* @throws org.apache.jackrabbit.ocm.exception.RepositoryException
* if the underlying repository has thrown a
* javax.jcr.RepositoryException
* @throws JcrMappingException
* if the mapping for the class is not correct
* @throws ObjectContentManagerException
* if the object cannot be retrieved from the path
*/
public Object getObject(String path) {
try {
if (!session.nodeExists(path)) {
return null;
}
} catch (RepositoryException e) {
throw new org.apache.jackrabbit.ocm.exception.RepositoryException("Impossible to get the object at " + path, e);
}
Object object = objectConverter.getObject(session, path);
requestObjectCache.clear();
return object;
}
/**
* @param uuid the <code>uuid</code> of the backing jcr node
* @return the Object for <code>uuid</code>
* @throws org.apache.jackrabbit.ocm.exception.RepositoryException
* if the underlying repository has thrown a javax.jcr.RepositoryException
* @throws JcrMappingException if the mapping for the class is not correct
* @throws ObjectContentManagerException if the object cannot be retrieved from the path
* @throws IllegalArgumentException when the <code>uuid</code> is <code>null</code> or not a valid UUID
*/
public Object getObjectByUuid(String uuid) {
try {
Node node = session.getNodeByIdentifier(uuid);
Object object = objectConverter.getObject(session, node.getPath());
requestObjectCache.clear();
return object;
} catch (RepositoryException e) {
throw new org.apache.jackrabbit.ocm.exception.RepositoryException("Impossible to get the object with uuid : " + uuid, e);
}
}
/**
*
* @param path the object's absolute jcr path
* @param versionName the version that needs to be fetched
* @return the Object for <code>path</code> and version <code>versionName</code> or <code>null</code> if there is no jcr node for the specified
* path and versionName
* @throws org.apache.jackrabbit.ocm.exception.RepositoryException
* if the underlying repository has thrown a
* javax.jcr.RepositoryException
* @throws JcrMappingException
* if the mapping for the class is not correct
* @throws ObjectContentManagerException
* if the object cannot be retrieved from the path and versionName
*/
public Object getObject(String path, String versionName) {
String pathVersion;
try {
if (!session.nodeExists(path)) {
return null;
}
Version version = this.getVersion(path, versionName);
pathVersion = version.getPath() + "/jcr:frozenNode";
} catch (RepositoryException e) {
throw new org.apache.jackrabbit.ocm.exception.RepositoryException("Impossible to get the object at " + path + " - version :" + versionName, e);
}
Object object = objectConverter.getObject(session, pathVersion);
requestObjectCache.clear();
return object;
}
/**
*
* @param objectClass the object mapping class
* @param path the object's absolute jcr path
* @return the Object for <code>path</code> pr <code>null</code> if there is no jcr node at <code>path</code>
* @throws org.apache.jackrabbit.ocm.exception.RepositoryException
* if the underlying repository has thrown a
* javax.jcr.RepositoryException
* @throws JcrMappingException
* if the mapping for the class is not correct
* @throws ObjectContentManagerException
* if the object cannot be retrieved from the path
*/
public Object getObject(Class objectClass, String path) {
try {
if (!session.nodeExists(path)) {
return null;
}
} catch (RepositoryException e) {
throw new org.apache.jackrabbit.ocm.exception.RepositoryException("Impossible to get the object at " + path, e);
}
Object object = objectConverter.getObject(session, objectClass, path);
requestObjectCache.clear();
return object;
}
public Object getObject(Class objectClass, String path, String versionName) {
String pathVersion = null;
try {
if (!session.nodeExists(path)) {
return null;
}
Version version = this.getVersion(path, versionName);
pathVersion = version.getPath() + "/jcr:frozenNode";
} catch (RepositoryException e) {
throw new org.apache.jackrabbit.ocm.exception.RepositoryException("Impossible to get the object at " + path + " - version :" + versionName, e);
}
Object object = objectConverter.getObject(session, objectClass, pathVersion);
requestObjectCache.clear();
return object;
}
public void retrieveAllMappedAttributes(Object object) {
objectConverter.retrieveAllMappedAttributes(session, object);
requestObjectCache.clear();
}
public void retrieveMappedAttribute(Object object, String attributeName) {
objectConverter.retrieveMappedAttribute(session, object, attributeName);
requestObjectCache.clear();
}
public void insert(Object object) {
String path = objectConverter.getPath(session, object);
try {
if (session.nodeExists(path)) {
Node node = session.getNode(path);
if (!node.getDefinition().allowsSameNameSiblings()) {
throw new ObjectContentManagerException("Path already exists and it is not supporting the same name sibling : " + path);
}
}
} catch (RepositoryException e) {
throw new org.apache.jackrabbit.ocm.exception.RepositoryException("Impossible to insert the object at " + path, e);
}
objectConverter.insert(session, object);
}
public void update(Object object) {
String path = objectConverter.getPath(session, object);
try {
if (!session.nodeExists(path)) {
throw new ObjectContentManagerException("Path is not existing : " + path);
} else {
checkIfNodeLocked(path);
}
} catch (javax.jcr.RepositoryException e) {
throw new org.apache.jackrabbit.ocm.exception.RepositoryException("Impossible to update", e);
}
objectConverter.update(session, object);
}
public void remove(String path) {
try {
if (!session.nodeExists(path)) {
throw new ObjectContentManagerException("Path does not exist : " + path);
} else {
checkIfNodeLocked(path);
}
Item item = session.getItem(path);
item.remove();
} catch (RepositoryException e) {
throw new org.apache.jackrabbit.ocm.exception.RepositoryException("Impossible to remove the object at " + path);
}
}
public void remove(Object object) {
this.remove(objectConverter.getPath(session, object));
}
public void remove(Query query) {
try {
String jcrExpression = this.queryManager.buildJCRExpression(query);
log.debug("Remove Objects with expression : " + jcrExpression);
// Since only nodes are sufficient for us to remove,
// getObjects(query, language) method is not called here.
@SuppressWarnings("deprecation")
NodeIterator nodeIterator = getNodeIterator(jcrExpression, javax.jcr.query.Query.XPATH);
List nodes = new ArrayList();
while (nodeIterator.hasNext()) {
Node node = nodeIterator.nextNode();
if (node == null) {
// node has been removed possibly by another thread during iterating through the results
continue;
}
log.debug("Remove node : " + node.getPath());
// it is not possible to remove nodes from an NodeIterator
// So, we add the node found in a collection to remove them
// after
nodes.add(node);
}
// Remove all collection nodes
for (int i = 0; i < nodes.size(); i++) {
Node node = (Node) nodes.get(i);
checkIfNodeLocked(node.getPath());
try {
node.remove();
} catch (javax.jcr.RepositoryException re) {
throw new ObjectContentManagerException("Cannot remove node at path " + node.getPath() + " returned from query " + jcrExpression, re);
}
}
} catch (InvalidQueryException iqe) {
throw new org.apache.jackrabbit.ocm.exception.RepositoryException("Invalid query expression", iqe);
} catch (RepositoryException e) {
throw new org.apache.jackrabbit.ocm.exception.RepositoryException("Impossible to get the object collection", e);
}
}
public boolean objectExists(String path) {
try {
return session.nodeExists(path);
} catch (RepositoryException e) {
throw new org.apache.jackrabbit.ocm.exception.RepositoryException("Impossible to check if the object exist", e);
}
}
public boolean isPersistent(final Class clazz) {
try {
ClassDescriptor classDescriptor = mapper.getClassDescriptorByClass(clazz);
if (classDescriptor == null) {
return false;
}
return true;
} catch (IncorrectPersistentClassException e) {
return false;
}
}
public Object getObject(Query query) {
String jcrExpression = this.queryManager.buildJCRExpression(query);
@SuppressWarnings("deprecation")
Collection result = getObjects(jcrExpression, javax.jcr.query.Query.XPATH);
if (result.size() > 1) {
throw new ObjectContentManagerException("Impossible to get the object - the query returns more than one object");
}
return result.isEmpty() ? null : result.iterator().next();
}
@SuppressWarnings("deprecation")
public Collection getObjects(Query query) {
String jcrExpression = this.queryManager.buildJCRExpression(query);
return getObjects(jcrExpression, javax.jcr.query.Query.XPATH);
}
public Collection getObjects(Class objectClass, String path) throws ObjectContentManagerException {
final ClassDescriptor classDescriptorByClass = mapper.getClassDescriptorByClass(objectClass);
if (classDescriptorByClass == null) {
log.debug("Cannot get objects because no descriptor class exists for '{}'", objectClass.getClass().getName());
return Collections.emptyList();
}
try {
if (!session.nodeExists(path)) {
log.debug("Cannot get objects '{}' because no node exists at '{}'", objectClass.getClass().getName(), path);
return Collections.emptyList();
}
Node parentNode = session.getNode(path).getParent();
String nodeName = NodeUtil.getNodeName(path);
if (StringUtils.isBlank(nodeName)) {
nodeName = null;
}
NodeIterator candidates = parentNode.getNodes();
List<Node> validated = new ArrayList<Node>();
while (candidates.hasNext()) {
Node child = candidates.nextNode();
if (nodeName != null && !child.getName().equals(nodeName)) {
continue;
}
if (child.hasProperty(ManagerConstant.DISCRIMINATOR_CLASS_NAME_PROPERTY)) {
if (child.getProperty(ManagerConstant.DISCRIMINATOR_CLASS_NAME_PROPERTY).getString().equals(classDescriptorByClass.getClassName())) {
// the discriminator class name matches. This is an object we need
validated.add(child);
}
} else {
if (child.getPrimaryNodeType().getName().equals(classDescriptorByClass.getJcrType())) {
// nodetype matches
validated.add(child);
}
}
}
Collection result = new ArrayList();
for (Node n : validated) {
Object object = objectConverter.getObject(session, n.getPath());
if (object == null) {
log.debug("Could not get object for '{}'", n.getPath());
continue;
}
// double check whether object is the same or a subclass of objectClass
if (objectClass.isAssignableFrom(object.getClass())) {
result.add(object);
}
}
return result;
} catch (RepositoryException e) {
throw new org.apache.jackrabbit.ocm.exception.RepositoryException("Impossible to get the objects at " + path, e);
}
}
public Iterator getObjectIterator(Query query) {
String jcrExpression = this.queryManager.buildJCRExpression(query);
log.debug("Get Object with expression : " + jcrExpression);
@SuppressWarnings("deprecation")
NodeIterator nodeIterator = getNodeIterator(jcrExpression, javax.jcr.query.Query.XPATH);
return new ObjectIterator(nodeIterator, this.objectConverter, this.session);
}
public Iterator getObjectIterator(String query, String language) {
log.debug("Get Object with expression : " + query);
NodeIterator nodeIterator = getNodeIterator(query, language);
return new ObjectIterator(nodeIterator, this.objectConverter, this.session);
}
public Collection getObjects(String query, String language) {
try {
log.debug("Get Objects with expression : " + query + " and language " + language);
NodeIterator nodeIterator = getNodeIterator(query, language);
List result = new ArrayList();
while (nodeIterator.hasNext()) {
Node node = nodeIterator.nextNode();
log.debug("Node found : " + node.getPath());
result.add(objectConverter.getObject(session, node.getPath()));
}
requestObjectCache.clear();
return result;
} catch (InvalidQueryException iqe) {
throw new org.apache.jackrabbit.ocm.exception.RepositoryException("Invalid query expression", iqe);
} catch (RepositoryException e) {
throw new org.apache.jackrabbit.ocm.exception.RepositoryException("Impossible to get the object collection", e);
}
}
private NodeIterator getNodeIterator(String query, String language) {
if (log.isDebugEnabled()) {
log.debug("Get Node Iterator with expression " + query + " and language " + language);
}
javax.jcr.query.Query jcrQuery;
try {
jcrQuery = session.getWorkspace().getQueryManager().createQuery(query, language);
QueryResult queryResult = jcrQuery.execute();
NodeIterator nodeIterator = queryResult.getNodes();
return nodeIterator;
} catch (InvalidQueryException iqe) {
throw new org.apache.jackrabbit.ocm.exception.InvalidQueryException(iqe);
} catch (RepositoryException re) {
throw new ObjectContentManagerException(re.getMessage(), re);
}
}
public void checkin(String path) {
this.checkin(path, null);
}
public void checkin(String path, String[] versionLabels) {
try {
Node node = (Node) session.getItem(path);
checkIfNodeLocked(node.getPath());
if (!node.isNodeType("mix:versionable")) {
throw new VersionException("The object " + path + "is not versionable");
}
javax.jcr.version.Version newVersion = getVersionManager().checkin(path);
if (versionLabels != null) {
VersionHistory versionHistory = getVersionManager().getVersionHistory(path);
for (int i = 0; i < versionLabels.length; i++) {
versionHistory.addVersionLabel(newVersion.getName(), versionLabels[i], false);
}
}
} catch (ClassCastException cce) {
throw new ObjectContentManagerException("Cannot retrieve an object from a property path " + path);
} catch (PathNotFoundException pnfe) {
throw new ObjectContentManagerException("Cannot retrieve an object at path " + path, pnfe);
} catch (InvalidItemStateException iise) {
throw new ObjectContentManagerException("Cannot checking modified object at path " + path, iise);
} catch (javax.jcr.version.VersionException ve) {
throw new VersionException("Impossible to checkin the object " + path, ve);
} catch (UnsupportedRepositoryOperationException uroe) {
throw new VersionException("Cannot checkin unversionable node at path " + path, uroe);
} catch (LockException le) {
throw new VersionException("Cannot checkin locked node at path " + path, le);
} catch (RepositoryException e) {
throw new org.apache.jackrabbit.ocm.exception.RepositoryException("Impossible to checkin the object " + path, e);
}
}
public void checkout(String path) {
Node node;
try {
node = (Node) session.getItem(path);
if (!node.isNodeType("mix:versionable")) {
throw new VersionException("The object " + path + "is not versionable");
}
getVersionManager().checkout(path);
} catch (ClassCastException cce) {
throw new ObjectContentManagerException("Cannot retrieve an object from a property path " + path);
} catch (PathNotFoundException pnfe) {
throw new ObjectContentManagerException("Cannot retrieve an object at path " + path, pnfe);
} catch (UnsupportedRepositoryOperationException uroe) {
throw new VersionException("Cannot checkout unversionable node at path " + path, uroe);
} catch (LockException le) {
throw new VersionException("Cannot checkout locked node at path " + path, le);
} catch (javax.jcr.RepositoryException e) {
throw new org.apache.jackrabbit.ocm.exception.RepositoryException("Impossible to checkout the object " + path, e);
}
}
public void addVersionLabel(String path, String versionName, String versionLabel) {
try {
Node node = (Node) session.getItem(path);
checkIfNodeLocked(path);
if (!node.isNodeType("mix:versionable")) {
throw new VersionException("The object " + path + "is not versionable");
}
VersionHistory history = getVersionManager().getVersionHistory(path);
history.addVersionLabel(versionName, versionLabel, false);
} catch (ClassCastException cce) {
throw new ObjectContentManagerException("Cannot retrieve an object from a property path " + path);
} catch (PathNotFoundException pnfe) {
throw new ObjectContentManagerException("Cannot retrieve an object at path " + path, pnfe);
} catch (javax.jcr.version.VersionException ve) {
throw new VersionException("Impossible to add a new version label to " + path + " - version name : " + versionName, ve);
} catch (UnsupportedRepositoryOperationException uroe) {
throw new VersionException("Impossible to add a new version label to " + path + " - version name : " + versionName, uroe);
} catch (javax.jcr.RepositoryException e) {
throw new org.apache.jackrabbit.ocm.exception.RepositoryException(e);
}
}
public Version getVersion(String path, String versionName) {
try {
Node node = (Node) session.getItem(path);
if (!node.isNodeType("mix:versionable")) {
throw new VersionException("The object " + path + "is not versionable");
}
VersionHistory history = getVersionManager().getVersionHistory(path);
return new Version(history.getVersion(versionName));
} catch (ClassCastException cce) {
throw new ObjectContentManagerException("Cannot retrieve an object from a property path " + path);
} catch (PathNotFoundException pnfe) {
throw new ObjectContentManagerException("Cannot retrieve an object at path " + path, pnfe);
} catch (javax.jcr.version.VersionException ve) {
throw new VersionException("The version name " + versionName + "does not exist", ve);
} catch (UnsupportedRepositoryOperationException uroe) {
throw new VersionException("Impossible to retrieve versions for path " + path, uroe);
} catch (javax.jcr.RepositoryException e) {
throw new org.apache.jackrabbit.ocm.exception.RepositoryException(e);
}
}
public String[] getVersionLabels(String path, String versionName) {
try {
Node node = (Node) session.getItem(path);
if (!node.isNodeType("mix:versionable")) {
throw new VersionException("The object " + path + "is not versionable");
}
VersionHistory history = getVersionManager().getVersionHistory(path);
javax.jcr.version.Version version = history.getVersion(versionName);
return history.getVersionLabels(version);
} catch (ClassCastException cce) {
throw new ObjectContentManagerException("Cannot retrieve an object from a property path " + path);
} catch (PathNotFoundException pnfe) {
throw new ObjectContentManagerException("Cannot retrieve an object at path " + path, pnfe);
} catch (javax.jcr.version.VersionException ve) {
throw new VersionException("Impossible to get the version labels : " + path + " - version name : " + versionName, ve);
} catch (UnsupportedRepositoryOperationException uroe) {
throw new VersionException("Impossible to retrieve versions for path " + path, uroe);
} catch (RepositoryException e) {
throw new org.apache.jackrabbit.ocm.exception.RepositoryException(e);
}
}
public String[] getAllVersionLabels(String path) {
try {
Node node = session.getNode(path);
if (!node.isNodeType("mix:versionable")) {
throw new VersionException("The object " + path + "is not versionable");
}
VersionHistory history = getVersionManager().getVersionHistory(path);
return history.getVersionLabels();
} catch (ClassCastException cce) {
throw new ObjectContentManagerException("Cannot retrieve an object from a property path " + path);
} catch (PathNotFoundException pnfe) {
throw new ObjectContentManagerException("Cannot retrieve an object at path " + path, pnfe);
} catch (UnsupportedRepositoryOperationException uroe) {
throw new VersionException("Impossible to retrieve version history for path " + path, uroe);
} catch (RepositoryException e) {
throw new org.apache.jackrabbit.ocm.exception.RepositoryException(e);
}
}
public VersionIterator getAllVersions(String path) {
try {
Node node = session.getNode(path);
if (!node.isNodeType("mix:versionable")) {
throw new VersionException("The object " + path + "is not versionable");
}
VersionHistory history = getVersionManager().getVersionHistory(path);
return new VersionIterator(history.getAllVersions());
} catch (ClassCastException cce) {
throw new ObjectContentManagerException("Cannot retrieve an object from a property path " + path);
} catch (PathNotFoundException pnfe) {
throw new ObjectContentManagerException("Cannot retrieve an object at path " + path, pnfe);
} catch (UnsupportedRepositoryOperationException uroe) {
throw new VersionException("Impossible to retrieve version history for path " + path, uroe);
} catch (RepositoryException e) {
throw new org.apache.jackrabbit.ocm.exception.RepositoryException(e);
}
}
public Version getRootVersion(String path) {
try {
Node node = session.getNode(path);
if (!node.isNodeType("mix:versionable")) {
throw new VersionException("The object " + path + "is not versionable");
}
VersionHistory history = getVersionManager().getVersionHistory(path);
return new Version(history.getRootVersion());
} catch (ClassCastException cce) {
throw new ObjectContentManagerException("Cannot retrieve an object from a property path " + path);
} catch (PathNotFoundException pnfe) {
throw new ObjectContentManagerException("Cannot retrieve an object at path " + path, pnfe);
} catch (UnsupportedRepositoryOperationException uroe) {
throw new VersionException("Impossible to get the root version for the object " + path, uroe);
} catch (RepositoryException e) {
throw new org.apache.jackrabbit.ocm.exception.RepositoryException(e);
}
}
public Version getBaseVersion(String path) {
try {
Node node = session.getNode(path);
if (!node.isNodeType("mix:versionable")) {
throw new VersionException("The object " + path + "is not versionable");
}
return new Version(getVersionManager().getBaseVersion(path));
} catch (ClassCastException cce) {
throw new ObjectContentManagerException("Cannot retrieve an object from a property path " + path);
} catch (PathNotFoundException pnfe) {
throw new ObjectContentManagerException("Cannot retrieve an object at path " + path, pnfe);
} catch (UnsupportedRepositoryOperationException uroe) {
throw new VersionException("Impossible to get the base version for the object " + path, uroe);
} catch (javax.jcr.RepositoryException e) {
throw new org.apache.jackrabbit.ocm.exception.RepositoryException(e);
}
}
public Lock lock(final String absPath, final boolean isDeep, final boolean isSessionScoped) throws LockedException {
try {
// Calling this method will throw exception if node is locked
// and this operation cant be done (exception translation)
checkIfNodeLocked(absPath);
javax.jcr.lock.Lock lock = getLockManager().lock(absPath, isDeep, isSessionScoped, 0L, session.getUserID());
return new Lock(lock);
} catch (LockException e) {
// Only one case with LockException remains: if node is not
// mix:lockable, propably error in custom node types definitions
throw new org.apache.jackrabbit.ocm.exception.RepositoryException("Node of type is not type mix:lockable", e);
} catch (RepositoryException e) {
throw new org.apache.jackrabbit.ocm.exception.RepositoryException(e.getMessage(), e);
}
}
public void unlock(final String absPath, final String lockToken) throws IllegalUnlockException {
String lockOwner = null;
try {
maybeAddLockToken(lockToken, absPath);
Node node = getNode(absPath);
if (node.isLocked() == false) {
// Safe - if not locked return
return;
}
javax.jcr.lock.Lock lock = getLockManager().getLock(absPath);
lockOwner = lock.getLockOwner();
getLockManager().unlock(absPath);
} catch (LockException e) {
// LockException if this node does not currently hold a lock (see
// upper code)
// or holds a lock for which this Session does not have the correct
// lock token
log.error("Cannot unlock path: " + absPath + " Jcr user: " + session.getUserID() + " has no lock token to do this. Lock was placed with user: " + lockOwner);
throw new IllegalUnlockException(lockOwner, absPath);
} catch (RepositoryException e) {
// This also catch UnsupportedRepositoryOperationException - we
// assume that implementation supports it (jackrabbit does)
throw new org.apache.jackrabbit.ocm.exception.RepositoryException(e.getMessage(), e);
}
}
public boolean isLocked(final String absPath) {
try {
final Node node = getNode(absPath);
return node.isLocked();
} catch (RepositoryException e) {
// node.isLocked() RepositoryException if an error occurs.
throw new org.apache.jackrabbit.ocm.exception.RepositoryException("An exception was thrown while checking the lock at path : " + absPath, e);
}
}
public QueryManager getQueryManager() {
return this.queryManager;
}
/**
* Throws {@link LockedException} id node is locked so alter nopde cannot be
* done
*
* @param absPath
* abs path to node
* @throws RepositoryException
* @throws LockedException
* if node is locked
*/
protected void checkIfNodeLocked(final String absPath) throws RepositoryException, LockedException {
Node node = getNode(absPath);
// Node can hold lock or can be locked with precedencor
if (node.isLocked()) {
javax.jcr.lock.Lock lock = getLockManager().getLock(absPath);
String lockOwner = lock.getLockOwner();
if (!session.getUserID().equals(lockOwner)) {
final String path = lock.getNode().getPath();
throw new LockedException(lockOwner, path);
}
}
}
protected void maybeAddLockToken(final String lockToken, final String path) {
if (lockToken != null) {
// This user (this instance of PM) potentionally placed lock so
// session already has lock token
String[] lockTokens = null;
try {
lockTokens = getLockManager().getLockTokens();
} catch (UnsupportedRepositoryOperationException ex) {
throw new LockedException(session.getUserID(), path);
} catch (RepositoryException ex) {
throw new org.apache.jackrabbit.ocm.exception.RepositoryException(ex.getMessage(), ex);
}
if (lockTokens != null) {
for (int i = 0; i < lockTokens.length; i++) {
if (lockTokens[i].equals(lockToken)) {
// we are already holding a lock
break;
}
}
} else {
try {
getLockManager().addLockToken(lockToken);
} catch (UnsupportedRepositoryOperationException ex) {
throw new LockedException(session.getUserID(), path);
} catch (RepositoryException ex) {
throw new org.apache.jackrabbit.ocm.exception.RepositoryException(ex.getMessage(), ex);
}
}
}
}
protected Node getNode(final String absPath) throws PathNotFoundException, RepositoryException {
if (!session.nodeExists(absPath)) {
throw new ObjectContentManagerException("No object stored on path: " + absPath);
}
return session.getNode(absPath);
}
public void logout() {
try {
log.debug("Logout. Persisting current session changes.");
this.session.save();
this.session.logout();
log.debug("Session closed");
} catch (NoSuchNodeTypeException nsnte) {
throw new JcrMappingException("Cannot persist current session changes. An unknown node type was used.", nsnte);
} catch (javax.jcr.version.VersionException ve) {
throw new VersionException("Cannot persist current session changes. Attempt to overwrite checked-in node", ve);
} catch (LockException le) {
throw new ObjectContentManagerException("Cannot persist current session changes. Violation of a lock detected", le);
} catch (javax.jcr.RepositoryException e) {
throw new ObjectContentManagerException("Cannot persist current session changes.", e);
}
}
public void save() {
try {
this.session.save();
} catch (NoSuchNodeTypeException nsnte) {
throw new JcrMappingException("Cannot persist current session changes. An unknown node type was used.", nsnte);
} catch (javax.jcr.version.VersionException ve) {
throw new VersionException("Cannot persist current session changes. Attempt to overwrite checked-in node", ve);
} catch (LockException le) {
throw new ObjectContentManagerException("Cannot persist current session changes. Violation of a lock detected", le);
} catch (RepositoryException e) {
throw new ObjectContentManagerException("Cannot persist current session changes.", e);
} finally {
requestObjectCache.clear();
}
}
public Session getSession() {
return this.session;
}
public void refresh(boolean keepChanges) {
try {
session.refresh(keepChanges);
} catch (RepositoryException e) {
throw new ObjectContentManagerException("Cannot refresh current session ", e);
}
}
public void move(String srcPath, String destPath) {
try {
session.move(srcPath, destPath);
} catch (javax.jcr.nodetype.ConstraintViolationException cve) {
throw new ObjectContentManagerException("Cannot move the object from " + srcPath + " to " + destPath + "."
+ " Violation of a nodetype or attempt to move under a property detected", cve);
} catch (javax.jcr.version.VersionException ve) {
throw new VersionException("Cannot move the object from " + srcPath + " to " + destPath + "." + " Parent node of source or destination is versionable and checked in ",
ve);
} catch (javax.jcr.AccessDeniedException ade) {
throw new ObjectContentManagerException("Cannot move the object from " + srcPath + " to " + destPath + "." + " Session does not have access permissions", ade);
} catch (javax.jcr.PathNotFoundException pnf) {
throw new ObjectContentManagerException("Cannot move the object from " + srcPath + " to " + destPath + "." + " Node at source or destination does not exist ", pnf);
} catch (javax.jcr.ItemExistsException ie) {
throw new ObjectContentManagerException("Cannot move the object from " + srcPath + " to " + destPath + "." + " It might already exist at destination path.", ie);
} catch (javax.jcr.lock.LockException le) {
throw new ObjectContentManagerException("Cannot move the object from " + srcPath + " to " + destPath + "." + "Violation of a lock detected", le);
} catch (javax.jcr.RepositoryException re) {
throw new ObjectContentManagerException("Cannot move the object from " + srcPath + " to " + destPath + ".", re);
}
}
public void copy(String srcPath, String destPath) {
Workspace workspace = session.getWorkspace();
try {
workspace.copy(srcPath, destPath);
} catch (javax.jcr.nodetype.ConstraintViolationException cve) {
throw new ObjectContentManagerException("Cannot copy the object from " + srcPath + " to " + destPath + "."
+ "Violation of a nodetype or attempt to copy under property detected ", cve);
} catch (javax.jcr.version.VersionException ve) {
throw new VersionException("Cannot copy the object from " + srcPath + " to " + destPath + "." + "Parent node of source or destination is versionable and checked in ",
ve);
} catch (javax.jcr.AccessDeniedException ade) {
throw new ObjectContentManagerException("Cannot copy the object from " + srcPath + " to " + destPath + "." + " Session does not have access permissions", ade);
} catch (javax.jcr.PathNotFoundException pnf) {
throw new ObjectContentManagerException("Cannot copy the object from " + srcPath + " to " + destPath + "." + "Node at source or destination does not exist ", pnf);
} catch (javax.jcr.ItemExistsException ie) {
throw new ObjectContentManagerException("Cannot copy the object from " + srcPath + " to " + destPath + "." + "It might already exist at destination path.", ie);
} catch (javax.jcr.lock.LockException le) {
throw new ObjectContentManagerException("Cannot copy the object from " + srcPath + " to " + destPath + "." + "Violation of a lock detected", le);
} catch (javax.jcr.RepositoryException re) {
throw new ObjectContentManagerException("Cannot copy the node from " + srcPath + " to " + destPath + ".", re);
}
}
private LockManager getLockManager() throws UnsupportedRepositoryOperationException, RepositoryException {
return session.getWorkspace().getLockManager();
}
private VersionManager getVersionManager() throws UnsupportedRepositoryOperationException, RepositoryException {
return session.getWorkspace().getVersionManager();
}
}