You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by fm...@apache.org on 2007/09/27 14:52:22 UTC
svn commit: r579995 -
/jackrabbit/trunk/contrib/jackrabbit-jcr-mapping/jcr-mapping/src/main/java/org/apache/jackrabbit/ocm/manager/objectconverter/impl/ObjectConverterImpl.java
Author: fmeschbe
Date: Thu Sep 27 05:52:21 2007
New Revision: 579995
URL: http://svn.apache.org/viewvc?rev=579995&view=rev
Log:
JCR-1145 ObjectConverterImpl.getObject(Session, Class, String) may not resolve mapping correctly for incompletely described mappings
Modified:
jackrabbit/trunk/contrib/jackrabbit-jcr-mapping/jcr-mapping/src/main/java/org/apache/jackrabbit/ocm/manager/objectconverter/impl/ObjectConverterImpl.java
Modified: jackrabbit/trunk/contrib/jackrabbit-jcr-mapping/jcr-mapping/src/main/java/org/apache/jackrabbit/ocm/manager/objectconverter/impl/ObjectConverterImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/jackrabbit-jcr-mapping/jcr-mapping/src/main/java/org/apache/jackrabbit/ocm/manager/objectconverter/impl/ObjectConverterImpl.java?rev=579995&r1=579994&r2=579995&view=diff
==============================================================================
--- jackrabbit/trunk/contrib/jackrabbit-jcr-mapping/jcr-mapping/src/main/java/org/apache/jackrabbit/ocm/manager/objectconverter/impl/ObjectConverterImpl.java (original)
+++ jackrabbit/trunk/contrib/jackrabbit-jcr-mapping/jcr-mapping/src/main/java/org/apache/jackrabbit/ocm/manager/objectconverter/impl/ObjectConverterImpl.java Thu Sep 27 05:52:21 2007
@@ -16,6 +16,7 @@
*/
package org.apache.jackrabbit.ocm.manager.objectconverter.impl;
+import java.lang.reflect.Modifier;
import java.util.Iterator;
import java.util.Map;
@@ -53,7 +54,7 @@
/**
* Default implementation for {@link ObjectConverterImpl}
- *
+ *
* @author <a href="mailto:christophe.lombart@gmail.com">Lombart Christophe </a>
* @author <a href='mailto:the_mindstorm[at]evolva[dot]ro'>Alexandru Popescu</a>
*/
@@ -68,10 +69,10 @@
private AtomicTypeConverterProvider atomicTypeConverterProvider;
private ProxyManager proxyManager;
-
+
private SimpleFieldsHelper simpleFieldsHelp;
-
- private ObjectCache requestObjectCache;
+
+ private ObjectCache requestObjectCache;
/**
* No-arg constructor.
@@ -81,12 +82,12 @@
/**
* Constructor
- *
+ *
* @param mapper
* The mapper to used
* @param converterProvider
* The atomic type converter provider
- *
+ *
*/
public ObjectConverterImpl(Mapper mapper, AtomicTypeConverterProvider converterProvider) {
this.mapper = mapper;
@@ -98,23 +99,23 @@
/**
* Constructor
- *
+ *
* @param mapper
* The mapper to used
* @param converterProvider
* The atomic type converter provider
- *
+ *
*/
public ObjectConverterImpl(Mapper mapper, AtomicTypeConverterProvider converterProvider, ProxyManager proxyManager, ObjectCache requestObjectCache) {
this.mapper = mapper;
this.atomicTypeConverterProvider = converterProvider;
this.proxyManager = proxyManager;
this.simpleFieldsHelp = new SimpleFieldsHelper(atomicTypeConverterProvider);
- this.requestObjectCache = requestObjectCache;
- }
+ this.requestObjectCache = requestObjectCache;
+ }
/**
* Set the <code>Mapper</code> used to solve mappings.
- *
+ *
* @param mapper
* a <code>Mapper</code>
*/
@@ -124,7 +125,7 @@
/**
* Sets the converter provider.
- *
+ *
* @param converterProvider
* an <code>AtomicTypeConverterProvider</code>
*/
@@ -153,7 +154,7 @@
}
/**
- *
+ *
* @see org.apache.jackrabbit.ocm.manager.objectconverter.ObjectConverter#insert(javax.jcr.Session,
* javax.jcr.Node, java.lang.String, java.lang.Object)
*/
@@ -188,7 +189,7 @@
}
}
- // Add mixin types defined in the associated interfaces
+ // Add mixin types defined in the associated interfaces
if (!classDescriptor.hasDiscriminator() && classDescriptor.hasInterfaces()) {
Iterator interfacesIterator = classDescriptor.getImplements().iterator();
while (interfacesIterator.hasNext()) {
@@ -199,15 +200,15 @@
}
}
- // If required, add the discriminator node type
+ // If required, add the discriminator node type
if (classDescriptor.hasDiscriminator()) {
mixinTypeName = ManagerConstant.DISCRIMINATOR_NODE_TYPE;
objectNode.addMixin(mixinTypeName);
objectNode.setProperty(ManagerConstant.DISCRIMINATOR_PROPERTY_NAME, ReflectionUtils.getBeanClass(object)
.getName());
}
-
-
+
+
} catch (NoSuchNodeTypeException nsnte) {
throw new JcrMappingException("Unknown mixin type " + mixinTypeName + " for mapped class " + object.getClass(), nsnte);
} catch (RepositoryException re) {
@@ -240,7 +241,7 @@
}
/**
- *
+ *
* @see org.apache.jackrabbit.ocm.manager.objectconverter.ObjectConverter#update(javax.jcr.Session,
* javax.jcr.Node, java.lang.String, java.lang.Object)
*/
@@ -276,9 +277,9 @@
if (requestObjectCache.isCached(path))
{
- return requestObjectCache.getObject(path);
- }
-
+ return requestObjectCache.getObject(path);
+ }
+
ClassDescriptor classDescriptor = null;
Node node = (Node) session.getItem(path);
if (node.hasProperty(ManagerConstant.DISCRIMINATOR_PROPERTY_NAME)) {
@@ -298,18 +299,18 @@
}
Object object = ReflectionUtils.newInstance(classDescriptor.getClassName());
-
+
if (! requestObjectCache.isCached(path))
{
requestObjectCache.cache(path, object);
}
- simpleFieldsHelp.retrieveSimpleFields(session, classDescriptor, node, object);
+ simpleFieldsHelp.retrieveSimpleFields(session, classDescriptor, node, object);
retrieveBeanFields(session, classDescriptor, node, path, object, false);
retrieveCollectionFields(session, classDescriptor, node, object, false);
-
+
return object;
-
+
} catch (PathNotFoundException pnfe) {
// HINT should never get here
throw new ObjectContentManagerException("Impossible to get the object at " + path, pnfe);
@@ -324,17 +325,17 @@
* @see org.apache.jackrabbit.ocm.manager.objectconverter.ObjectConverter#getObject(javax.jcr.Session,
* java.lang.Class, java.lang.String)
*/
- public Object getObject(Session session, Class clazz, String path)
+ public Object getObject(Session session, Class clazz, String path)
{
try {
if (!session.itemExists(path)) {
return null;
}
-
+
if (requestObjectCache.isCached(path))
{
- return requestObjectCache.getObject(path);
- }
+ return requestObjectCache.getObject(path);
+ }
ClassDescriptor classDescriptor = getClassDescriptor(clazz);
@@ -356,30 +357,47 @@
String nodeType = node.getPrimaryNodeType().getName();
if (!nodeType.equals(classDescriptor.getJcrType())) {
alternativeDescriptor = classDescriptor.getDescendantClassDescriptor(nodeType);
+
+ // in case we an alternative could not be found by walking
+ // the class descriptor hierarchy, check whether we would
+ // have a descriptor for the node type directly (which
+ // may the case if the class descriptor hierarchy is
+ // incomplete due to missing configuration. See JCR-1145
+ // for details.
+ if (alternativeDescriptor == null) {
+ alternativeDescriptor = mapper.getClassDescriptorByNodeType(nodeType);
+ }
}
}
}
// if we have an alternative class descriptor, check whether its
- // extends (or is the same) as the requested class.
+ // extends (or is the same) as the requested class.
if (alternativeDescriptor != null) {
Class alternativeClazz = ReflectionUtils.forName(alternativeDescriptor.getClassName());
if (clazz.isAssignableFrom(alternativeClazz)) {
+ clazz = alternativeClazz;
classDescriptor = alternativeDescriptor;
}
}
-
+
+ // ensure class is concrete (neither interface nor abstract)
+ if (clazz.isInterface() || Modifier.isAbstract(clazz.getModifiers())) {
+ throw new JcrMappingException( "Cannot instantiate non-concrete class " + clazz.getName()
+ + " for node " + path + " of type " + node.getPrimaryNodeType().getName());
+ }
+
Object object = ReflectionUtils.newInstance(classDescriptor.getClassName());
-
+
if (! requestObjectCache.isCached(path))
{
requestObjectCache.cache(path, object);
}
-
- simpleFieldsHelp.retrieveSimpleFields(session, classDescriptor, node, object);
+
+ simpleFieldsHelp.retrieveSimpleFields(session, classDescriptor, node, object);
retrieveBeanFields(session, classDescriptor, node, path, object, false);
retrieveCollectionFields(session, classDescriptor, node, object, false);
-
+
return object;
} catch (PathNotFoundException pnfe) {
// HINT should never get here
@@ -398,7 +416,7 @@
Node node = (Node) session.getItem(path);
retrieveBeanFields(session, classDescriptor, node, path, object, true);
retrieveCollectionFields(session, classDescriptor, node, object, true);
-
+
} catch (PathNotFoundException pnfe) {
throw new ObjectContentManagerException("Impossible to get the object at " + path, pnfe);
@@ -418,7 +436,7 @@
BeanDescriptor beanDescriptor = classDescriptor.getBeanDescriptor(attributeName);
if (beanDescriptor != null)
{
- this.retrieveBeanField(session, beanDescriptor, node, path, object, true);
+ this.retrieveBeanField(session, beanDescriptor, node, path, object, true);
}
// Check if the attribute is a collection
else
@@ -430,11 +448,11 @@
}
else
{
- throw new ObjectContentManagerException("Impossible to retrieve the mapped attribute. The attribute '" +
+ throw new ObjectContentManagerException("Impossible to retrieve the mapped attribute. The attribute '" +
attributeName + "' is not a bean or a collection for the class : " + classDescriptor.getClassName());
}
}
-
+
} catch (PathNotFoundException pnfe) {
throw new ObjectContentManagerException("Impossible to get the object at " + path, pnfe);
@@ -445,7 +463,7 @@
/**
* Validates the node type used by the class descriptor.
- *
+ *
* @param session
* the current session
* @param classDescriptor
@@ -483,7 +501,7 @@
/**
* Checks if the node type in the class descriptor is compatible with the
* specified node node type.
- *
+ *
* @param session
* the current session
* @param node
@@ -494,7 +512,7 @@
* <tt>true</tt> if the check should continue in case the
* <tt>node</tt> is a version node, <tt>false</tt> if no
* check against version node should be performed
- *
+ *
* @throws ObjectContentManagerException
* thrown if node types are incompatible
* @throws org.apache.jackrabbit.ocm.exception.RepositoryException
@@ -526,7 +544,7 @@
/**
* Node types compatibility check.
- *
+ *
* @param nodeType
* target node type
* @param descriptor
@@ -587,31 +605,31 @@
}
}
-
+
private void retrieveBeanField(Session session,BeanDescriptor beanDescriptor, Node node, String path, Object object, boolean forceToRetrieve )
{
- if (!beanDescriptor.isAutoRetrieve() && !forceToRetrieve)
+ if (!beanDescriptor.isAutoRetrieve() && !forceToRetrieve)
{
return;
}
-
+
String beanName = beanDescriptor.getFieldName();
String beanPath = ObjectContentManagerUtil.getPath(session, beanDescriptor, node);
-
+
Object bean = null;
if (requestObjectCache.isCached(beanPath))
{
- bean = requestObjectCache.getObject(beanPath);
- ReflectionUtils.setNestedProperty(object, beanName, bean);
+ bean = requestObjectCache.getObject(beanPath);
+ ReflectionUtils.setNestedProperty(object, beanName, bean);
}
- else
+ else
{
Class beanClass = ReflectionUtils.getPropertyType(object, beanName);
-
-
- String converterClassName = null;
- if (null == beanDescriptor.getConverter() || "".equals(beanDescriptor.getConverter()))
+
+
+ String converterClassName = null;
+ if (null == beanDescriptor.getConverter() || "".equals(beanDescriptor.getConverter()))
{
converterClassName = DEFAULT_BEAN_CONVERTER;
}
@@ -619,24 +637,24 @@
{
converterClassName = beanDescriptor.getConverter();
}
-
- Object[] param = {this.mapper, this, this.atomicTypeConverterProvider};
+
+ Object[] param = {this.mapper, this, this.atomicTypeConverterProvider};
BeanConverter beanConverter = (BeanConverter) ReflectionUtils.invokeConstructor(converterClassName, param);
- if (beanDescriptor.isProxy())
+ if (beanDescriptor.isProxy())
{
bean = proxyManager.createBeanProxy(session, this, beanClass, beanConverter.getPath(session, beanDescriptor, node));
- }
+ }
else
{
bean = beanConverter.getObject(session, node, beanDescriptor, mapper.getClassDescriptorByClass(beanClass), beanClass, bean);
- }
- requestObjectCache.cache(beanPath, bean);
+ }
+ requestObjectCache.cache(beanPath, bean);
ReflectionUtils.setNestedProperty(object, beanName, bean);
}
}
-
-
-
+
+
+
/**
* Retrieve Collection fields
*/
@@ -645,7 +663,7 @@
Iterator collectionDescriptorIterator = classDescriptor.getCollectionDescriptors().iterator();
while (collectionDescriptorIterator.hasNext()) {
CollectionDescriptor collectionDescriptor = (CollectionDescriptor) collectionDescriptorIterator.next();
- this.retrieveCollectionField(session, collectionDescriptor, parentNode, object, forceToRetrieve);
+ this.retrieveCollectionField(session, collectionDescriptor, parentNode, object, forceToRetrieve);
}
}
@@ -666,9 +684,9 @@
collection = collectionConverter.getCollection(session, parentNode, collectionDescriptor, collectionFieldClass);
}
- ReflectionUtils.setNestedProperty(object, collectionDescriptor.getFieldName(), collection);
+ ReflectionUtils.setNestedProperty(object, collectionDescriptor.getFieldName(), collection);
}
-
+
/**
* Insert Bean fields
*/
@@ -683,11 +701,11 @@
String jcrName = beanDescriptor.getJcrName();
Object bean = ReflectionUtils.getNestedProperty(object, beanDescriptor.getFieldName());
- if (bean != null)
+ if (bean != null)
{
String converterClassName = null;
-
- if (null == beanDescriptor.getConverter() || "".equals(beanDescriptor.getConverter()))
+
+ if (null == beanDescriptor.getConverter() || "".equals(beanDescriptor.getConverter()))
{
converterClassName = DEFAULT_BEAN_CONVERTER;
}
@@ -695,7 +713,7 @@
{
converterClassName = beanDescriptor.getConverter();
}
-
+
Object[] param = {this.mapper, this, this.atomicTypeConverterProvider};
BeanConverter beanConverter = (BeanConverter) ReflectionUtils.invokeConstructor(converterClassName, param);
beanConverter.insert(session, objectNode, beanDescriptor, mapper.getClassDescriptorByClass(bean.getClass()), bean, classDescriptor, object);
@@ -709,7 +727,7 @@
private void updateBeanFields(Session session, Object object, ClassDescriptor classDescriptor, Node objectNode) {
String jcrName = null;
Iterator beanDescriptorIterator = classDescriptor.getBeanDescriptors().iterator();
- while (beanDescriptorIterator.hasNext())
+ while (beanDescriptorIterator.hasNext())
{
BeanDescriptor beanDescriptor = (BeanDescriptor) beanDescriptorIterator.next();
if (!beanDescriptor.isAutoUpdate()) {
@@ -718,27 +736,27 @@
jcrName = beanDescriptor.getJcrName();
Object bean = ReflectionUtils.getNestedProperty(object, beanDescriptor.getFieldName());
-
+
String converterClassName = null;
- if (null == beanDescriptor.getConverter() || "".equals(beanDescriptor.getConverter()))
+ if (null == beanDescriptor.getConverter() || "".equals(beanDescriptor.getConverter()))
{
converterClassName = DEFAULT_BEAN_CONVERTER;
- }
- else
+ }
+ else
{
converterClassName = beanDescriptor.getConverter();
}
-
+
Object[] param = {this.mapper, this, this.atomicTypeConverterProvider };
BeanConverter beanConverter = (BeanConverter) ReflectionUtils.invokeConstructor(converterClassName, param);
Class beanClass = ReflectionUtils.getPropertyType(object, beanDescriptor.getFieldName());
// if the bean is null, remove existing node
- if ((bean == null))
+ if ((bean == null))
{
-
+
beanConverter.remove(session, objectNode, beanDescriptor, mapper.getClassDescriptorByClass(beanClass), bean, classDescriptor, object);
- } else
+ } else
{
beanConverter.update(session, objectNode, beanDescriptor, mapper.getClassDescriptorByClass(beanClass), bean, classDescriptor, object);
}