Index: xml/src/main/java/org/exolab/castor/xml/util/JDOClassDescriptorResolverImpl.java =================================================================== --- xml/src/main/java/org/exolab/castor/xml/util/JDOClassDescriptorResolverImpl.java (revision 7639) +++ xml/src/main/java/org/exolab/castor/xml/util/JDOClassDescriptorResolverImpl.java (working copy) @@ -1,26 +1,63 @@ package org.exolab.castor.xml.util; +import java.util.ArrayList; import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; import java.util.Map; import org.exolab.castor.mapping.ClassDescriptor; import org.exolab.castor.mapping.MappingLoader; import org.exolab.castor.xml.ClassDescriptorResolver; import org.exolab.castor.xml.ResolverException; +import org.exolab.castor.xml.util.resolvers.ResolveHelpers; public class JDOClassDescriptorResolverImpl implements ClassDescriptorResolver { - private Map _classToClassDescriptors = new HashMap(); + /** + * File name prefix used for JDO-specific descriptor classes. + */ + private static final String JDO_DESCRIPTOR_PREFIX = "JDO"; + + /** + * File name suffix used for JDO-specific descriptor classes. + */ + private static final String JDO_DESCRIPTOR_SUFFIX = "Descriptor"; + + /** + * Package name of the sub-package where descriptors can be found. + */ + private static final String JDO_DESCRIPTOR_PACKAGE = "descriptors"; + + /** + * A key ({@link Class}) value ({@link ClassDescriptor}) + * pair to cache already resolved jdo class descriptors. + */ + private Map _classDescriptorCache = new HashMap(); + private MappingLoader _mappingLoader; + /** + * List of manually added domain Classes. + */ + private List _classes = new LinkedList(); + public JDOClassDescriptorResolverImpl() { super(); } /** - * Returns the ClassDescriptor for the given class - * - * @param type the Class to find the ClassDescriptor for + * Returns the ClassDescriptor for the given class using the following + * strategy.

+ * + * + * @param type + * the Class to find the ClassDescriptor for * @return the ClassDescriptor for the given class */ public ClassDescriptor resolve(Class type) throws ResolverException { @@ -28,43 +65,97 @@ return null; } + ClassDescriptor classDesc; + // TODO: use ClassDescriptor instead - ClassDescriptor classDesc = (ClassDescriptor) _classToClassDescriptors.get(type); + classDesc = (ClassDescriptor) _classDescriptorCache.get(type); + if (classDesc != null) { + return classDesc; + } + classDesc = loadClassDescriptor(type); if (classDesc != null) { return classDesc; } - // -- check mapping loader first + // -- check mapping if (_mappingLoader != null) { classDesc = _mappingLoader.getDescriptor(type.getName()); if (classDesc != null) { - _classToClassDescriptors.put(type, classDesc); + _classDescriptorCache.put(type, classDesc); return classDesc; } } // TODO: consider for future extensions -// String pkgName = getPackageName(type.getName()); -// -// //-- check package mapping -// Mapping mapping = loadPackageMapping(pkgName, type.getClassLoader()); -// if (mapping != null) { -// try { -// MappingLoader mappingLoader = mapping.getResolver(BindingType.JDO); -// classDesc = mappingLoader.getDescriptor(type); -// } -// catch(MappingException mx) {} -// if (classDesc != null) { -// associate(type, classDesc); -// return classDesc; -// } -// } + // String pkgName = getPackageName(type.getName()); + // + // //-- check package mapping + // Mapping mapping = loadPackageMapping(pkgName, type.getClassLoader()); + // if (mapping != null) { + // try { + // MappingLoader mappingLoader = mapping.getResolver(BindingType.JDO); + // classDesc = mappingLoader.getDescriptor(type); + // } + // catch(MappingException mx) {} + // if (classDesc != null) { + // associate(type, classDesc); + // return classDesc; + // } + // } return classDesc; } // -- resolve + /** + * Tries to load a {@link ClassDescriptor} for the given type + * from the filesystem using a {@link ClassLoader} by + * . + * + * @param type to lookup the descriptor for. + * @return an instance of ClassDescriptor if found. null if not. + */ + private ClassDescriptor loadClassDescriptor(final Class type) { + ClassDescriptor classDesc = null; + ClassLoader classLoader = type.getClassLoader(); + StringBuffer descriptorClassName = new StringBuffer(type.getName()); + descriptorClassName.append(JDO_DESCRIPTOR_PREFIX); + descriptorClassName.append(JDO_DESCRIPTOR_SUFFIX); + // Try to load descriptor in the same package + Class descriptorClass = ResolveHelpers.loadClass( + classLoader, descriptorClassName.toString()); + + // If descriptor was not found, lookup the descriptor package + if (descriptorClass == null) { + int offset = descriptorClassName.lastIndexOf("."); + if (offset != -1) { + descriptorClassName.insert(offset , "."); + descriptorClassName.insert(offset + 1, JDO_DESCRIPTOR_PACKAGE); + descriptorClass = ResolveHelpers.loadClass( + classLoader, descriptorClassName.toString()); + } + } + + // Descriptor was found, instantiate and return it + if (descriptorClass != null) { + try { + classDesc = (ClassDescriptor) descriptorClass.newInstance(); + // Put descriptor into cache + _classDescriptorCache.put(type.getName(), classDesc); + return classDesc; + } catch (InstantiationException e) { + new RuntimeException(e.getMessage()); + } catch (IllegalAccessException e) { + new RuntimeException(e.getMessage()); + } + } + return classDesc; + } + public MappingLoader getMappingLoader() { return _mappingLoader; } @@ -73,4 +164,24 @@ this._mappingLoader = mappingLoader; } + public void addClass(Class domainClass) { + _classes.add(domainClass); + } + + /** + * Returns an iterator over all the known descriptors in the original order they have been + * added. Each element is of type {@link ClassDescriptor}. + */ + public Iterator descriptorIterator() { + List allDescriptors = new ArrayList(); + allDescriptors.addAll(_mappingLoader.getDescriptors()); + for (Iterator iterator = _classes.iterator(); iterator.hasNext();) { + allDescriptors.add(loadClassDescriptor((Class) iterator.next())); + } + return allDescriptors.iterator(); + } + + public ClassLoader getClassLoader() { + return _mappingLoader.getClassLoader(); + } } Index: xml/src/main/java/org/exolab/castor/mapping/MappingLoader.java =================================================================== --- xml/src/main/java/org/exolab/castor/mapping/MappingLoader.java (revision 7639) +++ xml/src/main/java/org/exolab/castor/mapping/MappingLoader.java (working copy) @@ -45,6 +45,7 @@ package org.exolab.castor.mapping; import java.util.Iterator; +import java.util.List; import org.castor.mapping.BindingType; @@ -89,4 +90,10 @@ * added. Each element is of type {@link ClassDescriptor}. */ Iterator descriptorIterator(); + + /** + * Returns a List of {@link ClassDescriptor}s of all known descriptors. + * @return List of {@link ClassDescriptor} + */ + List getDescriptors(); } Index: xml/src/main/java/org/exolab/castor/mapping/loader/AbstractMappingLoader2.java =================================================================== --- xml/src/main/java/org/exolab/castor/mapping/loader/AbstractMappingLoader2.java (revision 7639) +++ xml/src/main/java/org/exolab/castor/mapping/loader/AbstractMappingLoader2.java (working copy) @@ -129,6 +129,10 @@ return _descriptors.iterator(); } + public final List getDescriptors() { + return _descriptors; + } + //-------------------------------------------------------------------------- /**