View Javadoc

    1   /* Copyright 2004, 2005 Acegi Technology Pty Limited
    2    *
    3    * Licensed under the Apache License, Version 2.0 (the "License");
    4    * you may not use this file except in compliance with the License.
    5    * You may obtain a copy of the License at
    6    *
    7    *     http://www.apache.org/licenses/LICENSE-2.0
    8    *
    9    * Unless required by applicable law or agreed to in writing, software
    10   * distributed under the License is distributed on an "AS IS" BASIS,
    11   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12   * See the License for the specific language governing permissions and
    13   * limitations under the License.
    14   */
    15
    16  package org.acegisecurity.domain.hibernate;
    17
    18  import org.acegisecurity.domain.validation.IntrospectionManager;
    19  import org.acegisecurity.domain.validation.ValidationRegistryManager;
    20
    21  import org.hibernate.EntityMode;
    22  import org.hibernate.Hibernate;
    23  import org.hibernate.HibernateException;
    24  import org.hibernate.SessionFactory;
    25
    26  import org.hibernate.metadata.ClassMetadata;
    27
    28  import org.hibernate.type.Type;
    29
    30  import org.springframework.beans.factory.InitializingBean;
    31
    32  import org.springframework.orm.hibernate3.HibernateSystemException;
    33
    34  import org.springframework.util.Assert;
    35
    36  import java.util.Collection;
    37  import java.util.Iterator;
    38  import java.util.List;
    39  import java.util.Map;
    40
    41
    42  /***
    43   * {@link IntrospectionManager} that uses Hibernate metadata to locate
    44   * children.
    45   *
    46   * <p>
    47   * Add children objects are added to the <code>List</code> of children objects
    48   * to validate, irrespective of whether a save/update/delete operation will
    49   * cascade to them. This is not a perfect solution, but addresses most
    50   * real-world validation requirements (you can always implement your own
    51   * <code>IntrospectionManager</code> if you prefer).
    52   * </p>
    53   *
    54   * <p>
    55   * This implementation only adds properties of a parent object that have a
    56   * Hibernate {@link net.sf.hibernate.type.Type} that indicates it is an object
    57   * type (ie {@link net.sf.hibernate.type.Type#isObjectType()}).
    58   * </p>
    59   *
    60   * @author Matthew Porter
    61   * @author Ben Alex
    62   */
    63  public class IntrospectionManagerHibernate implements IntrospectionManager,
    64      InitializingBean {
    65      //~ Instance fields ========================================================
    66
    67      private SessionFactory[] sessionFactories;
    68      private ValidationRegistryManager validationRegistryManager;
    69
    70      //~ Methods ================================================================
    71
    72      public void setSessionFactories(SessionFactory[] sessionFactorys) {
    73          this.sessionFactories = sessionFactorys;
    74      }
    75
    76      public SessionFactory[] getSessionFactories() {
    77          return this.sessionFactories;
    78      }
    79
    80      public void setValidationRegistryManager(
    81          ValidationRegistryManager validationRegistryManager) {
    82          this.validationRegistryManager = validationRegistryManager;
    83      }
    84
    85      public ValidationRegistryManager getValidationRegistryManager() {
    86          return validationRegistryManager;
    87      }
    88
    89      public void afterPropertiesSet() throws Exception {
    90          Assert.notNull(validationRegistryManager, "ValidationRegistryManager is required");
    91          Assert.notNull(sessionFactories, "SessionFactories are required");
    92          Assert.notEmpty(sessionFactories, "SessionFactories are required");
    93
    94          // Eagerly pre-register Validators for all Hibernate metadata-defined classes
    95          for (int i = 0; i < sessionFactories.length; i++) {
    96      		Map<String,ClassMetadata> metadataMap = this.sessionFactories[i].getAllClassMetadata();
    97              Collection<String> mappedClasses = metadataMap.keySet();
    98
    99              for (Iterator<String> iter = mappedClasses.iterator(); iter.hasNext();) {
    100                 String className = iter.next();
    101                 this.validationRegistryManager.findValidator(Class.forName(className));
    102             }
    103         }
    104     }
    105
    106     public void obtainImmediateChildren(Object parentObject, List<Object> allObjects) {
    107         Assert.notNull(parentObject,
    108             "Violation of interface contract: parentObject null");
    109         Assert.notNull(allObjects,
    110             "Violation of interface contract: allObjects null");
    111
    112         ClassMetadata classMetadata = null;
    113
    114         try {
    115             classMetadata = findMetadata(parentObject.getClass());
    116
    117             if (classMetadata != null) {
    118                 String[] propertyNames = classMetadata.getPropertyNames();
    119
    120                 for (int i = 0; i < propertyNames.length; i++) {
    121                     Type propertyType = classMetadata.getPropertyType(propertyNames[i]);
    122
    123                     // Add this property to the List of Objects to validate
    124                     // only if a Validator is registered for that Object AND
    125 					// the object is initialized (ie not lazy loaded)
    126                     if (this.validationRegistryManager.findValidator(
    127                             propertyType.getReturnedClass()) != null) {
    128                         Object childObject = classMetadata.getPropertyValue(parentObject, propertyNames[i], EntityMode.POJO);
    129                         if (childObject != null && Hibernate.isInitialized(childObject)) {
    130                             allObjects.add(childObject);
    131                         }
    132                     }
    133                 }
    134             }
    135         } catch (HibernateException he) {
    136             throw new HibernateSystemException(he);
    137         }
    138     }
    139
    140     private ClassMetadata findMetadata(Class clazz) throws HibernateSystemException {
    141     	for (int i = 0; i < sessionFactories.length; i++) {
    142     		ClassMetadata result = sessionFactories[i].getClassMetadata(clazz);
    143     		if (result != null) {
    144     			return result;
    145     		}
    146     	}
    147     	return null;
    148     }
    149 }