Remove Domain sub-project.
This commit is contained in:
parent
4c8029d234
commit
5ef0a1a4e6
|
@ -1,5 +0,0 @@
|
|||
target
|
||||
.settings
|
||||
.classpath
|
||||
.project
|
||||
.wtpmodules
|
|
@ -1,42 +0,0 @@
|
|||
<!--
|
||||
* ========================================================================
|
||||
*
|
||||
* Copyright 2004, 2005 Acegi Technology Pty Limited
|
||||
*
|
||||
* Licensed 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.
|
||||
*
|
||||
* ========================================================================
|
||||
-->
|
||||
|
||||
<project
|
||||
xmlns:j="jelly:core"
|
||||
xmlns:ant="jelly:ant"
|
||||
xmlns:util="jelly:util"
|
||||
xmlns:maven="jelly:maven"
|
||||
>
|
||||
<!--
|
||||
Disabled signing the domain JAR for now because it causes Hibernate issues
|
||||
if people subclass from the net.sf.acegitech.domain.impl package.
|
||||
|
||||
<postGoal name="jar:jar">
|
||||
<j:if test="${context.getVariable('signature.alias') != null}">
|
||||
<echo>signature.alias defined; signing JAR(s)...</echo>
|
||||
<ant:signjar lazy="true" alias="${signature.alias}" storepass="${signature.storepass}" keystore="${signature.keystore}">
|
||||
<fileset dir="${maven.build.dir}">
|
||||
<include name="*.jar"/>
|
||||
</fileset>
|
||||
</ant:signjar>
|
||||
</j:if>
|
||||
</postGoal>
|
||||
-->
|
||||
</project>
|
|
@ -1,44 +0,0 @@
|
|||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.acegisecurity</groupId>
|
||||
<artifactId>acegi-security-parent</artifactId>
|
||||
<version>1.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>acegi-security-domain</artifactId>
|
||||
<name>Acegi Security System for Spring - Domain Object Support</name>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.acegisecurity</groupId>
|
||||
<artifactId>acegi-security</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.hibernate</groupId>
|
||||
<artifactId>hibernate</artifactId>
|
||||
<version>3.0.3</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-hibernate3</artifactId>
|
||||
<version>2.0-m2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-beanutils</groupId>
|
||||
<artifactId>commons-beanutils</artifactId>
|
||||
<version>1.6.1</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<source>1.5</source>
|
||||
<target>1.5</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
|
@ -1,12 +0,0 @@
|
|||
# $Id$
|
||||
|
||||
# Values in this file will be overriden by any values with the same name
|
||||
# in the user-created build.properties file.
|
||||
|
||||
# Compile settings
|
||||
#
|
||||
# Java 1.5 is required because we use enums extensively in this subproject
|
||||
# (main Acegi Security project / parent) is Java 1.3 compatible
|
||||
#
|
||||
maven.compile.target=1.5
|
||||
maven.compile.source=1.5
|
|
@ -1,60 +0,0 @@
|
|||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<project>
|
||||
<extend>${basedir}/../project.xml</extend>
|
||||
<pomVersion>3</pomVersion>
|
||||
<artifactId>acegi-security-domain</artifactId>
|
||||
<name>Acegi Security System for Spring - Domain Object Support</name>
|
||||
<siteDirectory>/home/groups/a/ac/acegisecurity/htdocs/multiproject/acegi-security-domain</siteDirectory>
|
||||
<repository>
|
||||
<connection>scm:svn:https://svn.sourceforge.net/svnroot/acegisecurity/trunk/acegisecurity</connection>
|
||||
<developerConnection>scm:svn:https://svn.sourceforge.net/svnroot/acegisecurity/trunk/acegisecurity</developerConnection>
|
||||
<url>http://svn.sourceforge.net/viewcvs.cgi/acegisecurity/trunk/acegisecurity/domain/</url>
|
||||
</repository>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>hibernate</groupId>
|
||||
<artifactId>hibernate</artifactId>
|
||||
<version>3.0.3</version>
|
||||
<type>jar</type>
|
||||
<url>http://www.hibernate.org</url>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-lang</groupId>
|
||||
<artifactId>commons-lang</artifactId>
|
||||
<version>2.0</version>
|
||||
<type>jar</type>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-beanutils</groupId>
|
||||
<artifactId>commons-beanutils</artifactId>
|
||||
<version>1.6.1</version>
|
||||
<type>jar</type>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.acegisecurity</groupId>
|
||||
<artifactId>acegi-security</artifactId>
|
||||
<version>1.0.3-SNAPSHOT</version>
|
||||
<type>jar</type>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-hibernate3</artifactId>
|
||||
<version>2.0-m2</version>
|
||||
<type>jar</type>
|
||||
<url>http://www.springframework.org</url>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>${basedir}/../</directory>
|
||||
<targetPath>META-INF</targetPath>
|
||||
<includes>
|
||||
<include>notice.txt</include>
|
||||
</includes>
|
||||
<filtering>false</filtering>
|
||||
</resource>
|
||||
</resources>
|
||||
</build>
|
||||
</project>
|
||||
|
|
@ -1,50 +0,0 @@
|
|||
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* Licensed 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.acegisecurity.domain;
|
||||
|
||||
import org.acegisecurity.AcegiSecurityException;
|
||||
|
||||
|
||||
/**
|
||||
* Abstract superclass for all exceptions related to domain object support subproject.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public abstract class DomainException extends AcegiSecurityException {
|
||||
//~ Constructors ===================================================================================================
|
||||
|
||||
/**
|
||||
* Constructs a <code>DomainException</code> with the specified message and
|
||||
* root cause.
|
||||
*
|
||||
* @param msg the detail message
|
||||
* @param t the root cause
|
||||
*/
|
||||
public DomainException(String msg, Throwable t) {
|
||||
super(msg, t);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a <code>DomainException</code> with the specified message and
|
||||
* no root cause.
|
||||
*
|
||||
* @param msg the detail message
|
||||
*/
|
||||
public DomainException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
}
|
|
@ -1,47 +0,0 @@
|
|||
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* Licensed 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.acegisecurity.domain;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
|
||||
/**
|
||||
* An interface that indicates an object is a <i>persistable entity</i>.
|
||||
*
|
||||
* <p>
|
||||
* A persistable entity is any object that is capable of being persisted,
|
||||
* typically via a {@link org.acegisecurity.domain.dao.Dao} implementation.
|
||||
* </p>
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public interface PersistableEntity {
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
/**
|
||||
* Provides a common getter for the persistence layer to obtain an identity, irrespective of the actual
|
||||
* type of identity used.<p>Typically a subclass will delegate to a <code>public SomePrimitiveWrapper
|
||||
* getId()</code> method. The necessity for the <code>getInternalId()</code> abstract method is solely because
|
||||
* the persistence layer needs a way of obtaining the identity irrespective of the actual identity implementation
|
||||
* choice.</p>
|
||||
* <p>Returning <code>null</code> from this method will indicate the object has never been saved. This
|
||||
* will likely be relied on by some <code>Dao</code> implementations.</p>
|
||||
*
|
||||
* @return the persistence identity of this instance
|
||||
*/
|
||||
public abstract Serializable getInternalId();
|
||||
}
|
|
@ -1,173 +0,0 @@
|
|||
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* Licensed 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.acegisecurity.domain.dao;
|
||||
|
||||
import org.acegisecurity.domain.PersistableEntity;
|
||||
|
||||
import org.springframework.dao.DataAccessException;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
* Provides fundamental DAO capabilities for a single concrete {@link
|
||||
* PersistableEntity}, using JDK 1.5 generics.
|
||||
*
|
||||
* <P>
|
||||
* This interface provides a portable approach to Data Access Object (DAO)
|
||||
* functionality across various object relational persistance solutions.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* It is not envisioned that this interface will provide <b>all</b> data access
|
||||
* requirements for applications, however it should provide all of the
|
||||
* standard create, read, update, delete (CRUD) and finder functions that are
|
||||
* routinely needed. Specialized subclasses (that provide finer-grained
|
||||
* functionality) of the <code>Dao</code> interface are encouraged.
|
||||
* </p>
|
||||
*
|
||||
* <P>
|
||||
* A <code>Dao</code> implementation (or a subclass of <code>Dao</code>) should
|
||||
* be the sole entry point into the persistance layer of an application. The
|
||||
* persistence layer should only respond to requests from the services layer.
|
||||
* The services layer is where all transaction demarcation, security
|
||||
* authorization, workflow and business logic should take place.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* Each <code>Dao</code> implementation will support one
|
||||
* <code>PersistableEntity</code> classes only. The supported
|
||||
* <code>PersistableEntity</code> class must be indicated via the {@link
|
||||
* #supports(Class)} method.
|
||||
* </p>
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public interface Dao<E extends PersistableEntity> {
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
/**
|
||||
* Create a new object, with the current {@link PersistableEntity#getInternalId()} value being ignored.
|
||||
*
|
||||
* @param value (without the identity property initialized)
|
||||
*
|
||||
* @throws DataAccessException DOCUMENT ME!
|
||||
*/
|
||||
public void create(E value) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Delete an object.
|
||||
*
|
||||
* @param value the value to delete
|
||||
*
|
||||
* @throws DataAccessException DOCUMENT ME!
|
||||
*/
|
||||
public void delete(E value) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Return all persistent instances, including subclasses.
|
||||
*
|
||||
* @return all persistence instances (an empty <code>List</code> will be returned if no matches are found)
|
||||
*
|
||||
* @throws DataAccessException DOCUMENT ME!
|
||||
*/
|
||||
public List<E> findAll() throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Find a <code>List</code> of <code>PersistableEntity</code>s, searched by their identifiers.
|
||||
*
|
||||
* @param ids collection of identifiers to locate
|
||||
*
|
||||
* @return the values with those identifiers (an empty <code>List</code> will be returned if no matches are found)
|
||||
*
|
||||
* @throws DataAccessException DOCUMENT ME!
|
||||
*/
|
||||
public List<E> findId(Collection<Serializable> ids)
|
||||
throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Load a persistent instance by its identifier, although some properties may be lazy loaded depending on
|
||||
* the underlying DAO implementation and/or persistence engine mapping document.
|
||||
*
|
||||
* @param id the identifier of the persistent instance desired to be retrieved
|
||||
*
|
||||
* @return the request item, or <code>null</code> if not found
|
||||
*
|
||||
* @throws DataAccessException DOCUMENT ME!
|
||||
*/
|
||||
public E readId(Serializable id) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Find persistent instances with properties matching those of the passed <code>PersistableEntity</code>.<P>Persistent
|
||||
* instances are matched on the basis of query by example. Properties whose value is <code>null</code>, empty
|
||||
* <code>String</code>s, and any <code>Collection</code>s are ignored in the query by example evaluation.</p>
|
||||
*
|
||||
* @param value parameters to filter on (the class of this object will be added to the filter)
|
||||
* @param firstElement the first result (start at zero to obtain all results)
|
||||
* @param maxElements the maximum number of results desired for this page of the result set
|
||||
* @param orderByAsc the property name of the <code>PersistableEntity</code> that should be used to order the
|
||||
* results
|
||||
*
|
||||
* @return the requested page of the result list (a properly formed <code>PaginatedList</code> is returned if no
|
||||
* results match)
|
||||
*
|
||||
* @throws DataAccessException DOCUMENT ME!
|
||||
*/
|
||||
public PaginatedList<E> scroll(E value, int firstElement, int maxElements, String orderByAsc)
|
||||
throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Find persistent instances with properties matching those of the passed <code>PersistableEntity</code>,
|
||||
* ignoring the class of the passed <code>PersistableEntity</code> (useful if you pass a superclass, as you want
|
||||
* to find all subclass instances which match).
|
||||
*
|
||||
* @param value parameters to filter on (the class of this object will NOT be added to the filter)
|
||||
* @param firstElement the first result (start at zero to obtain all results)
|
||||
* @param maxElements the maximum number of results desired for this page of the result set
|
||||
* @param orderByAsc the property name of the <code>PersistableEntity</code> that should be used to order the
|
||||
* results
|
||||
*
|
||||
* @return the requested page of the result list (a properly formed <code>PaginatedList</code> is returned if no
|
||||
* results match)
|
||||
*
|
||||
* @throws DataAccessException DOCUMENT ME!
|
||||
*/
|
||||
public PaginatedList<E> scrollWithSubclasses(E value, int firstElement, int maxElements, String orderByAsc)
|
||||
throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Indicates whether the DAO instance provides persistence services for the specified class.
|
||||
*
|
||||
* @param clazz to test, which should be an implementation of <code>PersistableEntity</code>
|
||||
*
|
||||
* @return <code>true</code> or <code>false</code>, indicating whether or not the passed class is supported by this
|
||||
* DAO instance
|
||||
*/
|
||||
public boolean supports(Class clazz);
|
||||
|
||||
/**
|
||||
* Update an object.
|
||||
*
|
||||
* @param value to update, with the <code>PersistableEntity</code> having a non-<code>null</code> identifier
|
||||
*
|
||||
* @throws DataAccessException DOCUMENT ME!
|
||||
*/
|
||||
public void update(E value) throws DataAccessException;
|
||||
}
|
|
@ -1,59 +0,0 @@
|
|||
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* Licensed 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.acegisecurity.domain.dao;
|
||||
|
||||
/**
|
||||
* <code>InheritableThreadLocal</code> which indicates whether a {@link Dao} implementation should be forced to
|
||||
* return a detached instance.<p>A detached instance is one which is no longer associated with the ORM mapper and
|
||||
* changes will therefore not be transparently persisted to the database.</p>
|
||||
* <p>Not all <code>Dao</code> implementations support the concept of detached instances.</p>
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*
|
||||
* @see java.lang.InheritableThreadLocal
|
||||
*/
|
||||
public class DetachmentContextHolder {
|
||||
//~ Static fields/initializers =====================================================================================
|
||||
|
||||
private static InheritableThreadLocal<Boolean> contextHolder = new InheritableThreadLocal<Boolean>();
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
/**
|
||||
* Returns the boolean value detachment policy which has been set for the current thread (defaults to
|
||||
* false).
|
||||
*
|
||||
* @return DOCUMENT ME!
|
||||
*/
|
||||
public static boolean isForceReturnOfDetachedInstances() {
|
||||
if (contextHolder.get() == null) {
|
||||
contextHolder.set(Boolean.FALSE);
|
||||
}
|
||||
|
||||
return contextHolder.get().booleanValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether or not detached domain object instances should be returned within the current thread of
|
||||
* execution.
|
||||
*
|
||||
* @param alwaysReturnDetached if true then detached instances should be returned.
|
||||
*/
|
||||
public static void setForceReturnOfDetachedInstances(boolean alwaysReturnDetached) {
|
||||
contextHolder.set(new Boolean(alwaysReturnDetached));
|
||||
}
|
||||
}
|
|
@ -1,44 +0,0 @@
|
|||
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* Licensed 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.acegisecurity.domain.dao;
|
||||
|
||||
import org.acegisecurity.domain.PersistableEntity;
|
||||
|
||||
|
||||
/**
|
||||
* Indicates an implementation capable of evicting {@link
|
||||
* org.acegisecurity.domain.PersistableEntity}s.
|
||||
*
|
||||
* <p>
|
||||
* Structured as a separate interface (rather than a subclass of
|
||||
* <code>Dao</code>), as it is not required for all persistence strategies.
|
||||
* </p>
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public interface EvictionCapable {
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
/**
|
||||
* Removes the indicated persistent instance from the DAO's internal map/session.<p>If the passed object
|
||||
* does not exist in the internal map/session, the invocation has no effect.</p>
|
||||
* <p>May throw an exception if the implementation so desires.</p>
|
||||
*
|
||||
* @param entity to remove from the internal map/session
|
||||
*/
|
||||
public void evict(PersistableEntity entity);
|
||||
}
|
|
@ -1,127 +0,0 @@
|
|||
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* Licensed 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.acegisecurity.domain.dao;
|
||||
|
||||
import org.acegisecurity.domain.PersistableEntity;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
|
||||
|
||||
/**
|
||||
* Convenience methods that support eviction of <code>PersistableEntity</code>s from those objects that implement
|
||||
* {@link EvictionCapable}.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class EvictionUtils {
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
/**
|
||||
* Evicts the <code>PersistableEntity</code> using the passed <code>Object</code> (provided that the passed
|
||||
* <code>Object</code> implements <code>EvictionCapable</code>).
|
||||
*
|
||||
* @param daoOrServices the potential source for <code>EvictionCapable</code> services (never <code>null</code>)
|
||||
* @param entity to evict (can be <code>null</code>)
|
||||
*/
|
||||
public static void evictIfRequired(Object daoOrServices, PersistableEntity entity) {
|
||||
EvictionCapable evictor = getEvictionCapable(daoOrServices);
|
||||
|
||||
if ((evictor != null) && (entity != null)) {
|
||||
evictor.evict(entity);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Evicts each <code>PersistableEntity</code> element of the passed <code>Collection</code> using the
|
||||
* passed <code>Object</code> (provided that the passed <code>Object</code> implements
|
||||
* <code>EvictionCapable</code>).
|
||||
*
|
||||
* @param daoOrServices the potential source for <code>EvictionCapable</code> services (never <code>null</code>)
|
||||
* @param collection whose members to evict (never <code>null</code>)
|
||||
*/
|
||||
public static void evictIfRequired(Object daoOrServices, Collection<?extends Object> collection) {
|
||||
Assert.notNull(collection, "Cannot evict a null Collection");
|
||||
|
||||
if (getEvictionCapable(daoOrServices) == null) {
|
||||
// save expense of iterating collection
|
||||
return;
|
||||
}
|
||||
|
||||
Iterator<?extends Object> iter = collection.iterator();
|
||||
|
||||
while (iter.hasNext()) {
|
||||
Object obj = iter.next();
|
||||
|
||||
if (obj instanceof PersistableEntity) {
|
||||
evictIfRequired(daoOrServices, (PersistableEntity) obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Evicts the <code>PersistableEntity</code> using the passed <code>Object</code> (provided that the passed
|
||||
* <code>Object</code> implements <code>EvictionCapable</code>), along with expressly evicting every
|
||||
* <code>PersistableEntity</code> returned by the <code>PersistableEntity</code>'s getters.
|
||||
*
|
||||
* @param daoOrServices the potential source for <code>EvictionCapable</code> services (never <code>null</code>)
|
||||
* @param entity to evict includnig its getter results (can be <code>null</code>)
|
||||
*/
|
||||
public static void evictPopulatedIfRequired(Object daoOrServices, PersistableEntity entity) {
|
||||
EvictionCapable evictor = getEvictionCapable(daoOrServices);
|
||||
|
||||
if ((evictor != null) && (entity != null)) {
|
||||
evictor.evict(entity);
|
||||
|
||||
Method[] methods = entity.getClass().getMethods();
|
||||
|
||||
for (int i = 0; i < methods.length; i++) {
|
||||
if (methods[i].getName().startsWith("get") && (methods[i].getParameterTypes().length == 0)) {
|
||||
try {
|
||||
Object result = methods[i].invoke(entity, new Object[] {});
|
||||
|
||||
if (result instanceof PersistableEntity) {
|
||||
evictor.evict((PersistableEntity) result);
|
||||
}
|
||||
} catch (Exception ignored) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtain the <code>EvictionCapable</code> from the passed argument, or <code>null</code>.
|
||||
*
|
||||
* @param daoOrServices to check if provides eviction services
|
||||
*
|
||||
* @return the <code>EvictionCapable</code> object or <code>null</code> if the object does not provide eviction
|
||||
* services
|
||||
*/
|
||||
private static EvictionCapable getEvictionCapable(Object daoOrServices) {
|
||||
Assert.notNull(daoOrServices, "Cannot evict if the object that may provide EvictionCapable is null");
|
||||
|
||||
if (daoOrServices instanceof EvictionCapable) {
|
||||
return (EvictionCapable) daoOrServices;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,81 +0,0 @@
|
|||
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* Licensed 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.acegisecurity.domain.dao;
|
||||
|
||||
/**
|
||||
* Indicates an implementation capable of initializing an object, such that
|
||||
* any lazy loading is guaranteed to have been completed.
|
||||
*
|
||||
* <p>
|
||||
* Structured as a separate interface (rather than a subclass of
|
||||
* <code>Dao</code>), as it is not required for all persistence strategies.
|
||||
* </p>
|
||||
*
|
||||
* <p>In general the recommended approach to lazy initialization is as follows:
|
||||
*
|
||||
* <ul>
|
||||
*
|
||||
* <li>Do not use OpenSessionInView. You can use it if you like, but you'll have
|
||||
* less difficulty in the long-run if you plan your use cases and adopt the other
|
||||
* recommendations below.</li>
|
||||
*
|
||||
* <li>Set your mapping documents to use lazy initialization where possible. Only
|
||||
* mark an association as eager loaded if <b>every</b> single use case requires it
|
||||
* and you are happy with this eager loading being reflected in a mapping document
|
||||
* instead of Java code.</li>
|
||||
*
|
||||
* <li>Subclass the <code>Dao</code> implementation and add use case specific finder/read
|
||||
* methods that will use the persistence engine's eager loading capabilities. <b>Generally
|
||||
* this approach will deliver the best overall application performance</b>, as you will
|
||||
* (i) only be eager loading if and when required and (ii) you are directly using the
|
||||
* persistence engine capabilities to do so. It also places the eager loading management
|
||||
* in the <code>Dao</code>, which is an ideal location to standardise it.</li>
|
||||
*
|
||||
* <li>If you would prefer to achieve persistence engine independence and/or reduce
|
||||
* the number of <code>Dao</code> subclasses that exist in your application, you may
|
||||
* prefer to modify your services layer so that it uses the <code>InitializationCapable</code>
|
||||
* interface. However, this interface should be used judiciously given that it does
|
||||
* not allow the persistence engine to optimise eager loading for given use cases
|
||||
* and (probably) will lead to a mixture of places where fetching logic can be obtained.</li>
|
||||
*
|
||||
* <p>Generally your best strategy is subclassing the <code>Dao</code>. It means the
|
||||
* most code, but it's also by far the most efficient and offers flexibility to further
|
||||
* fine-tune specific use cases. Whichever way you go, try to be consistent throughout
|
||||
* your application (this will ease your future migration and troubleshooting needs).
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public interface InitializationCapable {
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
/**
|
||||
* Initializes the indicated object.<p>May throw an exception if the implementation so desires.</p>
|
||||
*
|
||||
* @param entity to initialize
|
||||
*/
|
||||
public void initialize(Object entity);
|
||||
|
||||
/**
|
||||
* Indicaets whether the passed object is initialized or not.
|
||||
*
|
||||
* @param entity to determine if initialized
|
||||
*
|
||||
* @return <code>true</code> if initialized, <code>false</code> is uninitialized or the initialization status is
|
||||
* unknown
|
||||
*/
|
||||
public boolean isInitialized(Object entity);
|
||||
}
|
|
@ -1,66 +0,0 @@
|
|||
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* Licensed 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.acegisecurity.domain.dao;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
|
||||
/**
|
||||
* Convenience methods that support initialization of lazily loaded collections and associations using DAOs and
|
||||
* other objects that implement {@link org.acegisecurity.domain.dao.InitializationCapable}.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class InitializationUtils {
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
/**
|
||||
* Initializes the passed entity using the passed DAO or services layer <code>Object</code> (provided that
|
||||
* the passed <code>Object</code> implements <code>InitializationCapable</code>).
|
||||
*
|
||||
* @param daoOrServices the potential source for <code>InitializationCapable</code> services (never
|
||||
* <code>null</code>)
|
||||
* @param entity to evict (can be <code>null</code>)
|
||||
*/
|
||||
public static void initializeIfRequired(Object daoOrServices, Object entity) {
|
||||
Assert.notNull(daoOrServices);
|
||||
|
||||
if (daoOrServices instanceof InitializationCapable) {
|
||||
((InitializationCapable) daoOrServices).initialize(entity);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether the passed entity has been initialized, by delegating to the passed daoOrServices
|
||||
* (provided that the passed daoOrServices implements <code>InitializationCapable</code>.
|
||||
*
|
||||
* @param daoOrServices DOCUMENT ME!
|
||||
* @param entity to determine whether initialized or not
|
||||
*
|
||||
* @return <code>true</code> if initialized, <code>false</code> if it is uninitialized or the passed daoOrServices
|
||||
* does not provide initialization querying support
|
||||
*/
|
||||
public static boolean isInitialized(Object daoOrServices, Object entity) {
|
||||
Assert.notNull(daoOrServices);
|
||||
|
||||
if (daoOrServices instanceof InitializationCapable) {
|
||||
return ((InitializationCapable) daoOrServices).isInitialized(entity);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -1,519 +0,0 @@
|
|||
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* Licensed 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.acegisecurity.domain.dao;
|
||||
|
||||
import org.acegisecurity.domain.PersistableEntity;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.Vector;
|
||||
|
||||
|
||||
/**
|
||||
* <p>JDK1.5 compatible paginated <code>List</code>.</p>
|
||||
* <p>Elements in the internal <code>List</code> (see {@link #getList()} represent only part of a larger
|
||||
* resultset.</p>
|
||||
* <p>Note that firstElement starts at zero. Any attempt to access other than the current page will cause an
|
||||
* error.</p>
|
||||
* <p>This is a read only implementation and many of the <code>List</code> methods are not implemented.</p>
|
||||
*
|
||||
* @author Carlos Sanchez
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*
|
||||
* @param <E> DOCUMENT ME!
|
||||
*/
|
||||
public class PaginatedList<E extends PersistableEntity> implements List<E> {
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
private List<E> list;
|
||||
protected final transient Log logger = LogFactory.getLog(getClass());
|
||||
private int firstElement;
|
||||
private int maxElements;
|
||||
private int size;
|
||||
|
||||
//~ Constructors ===================================================================================================
|
||||
|
||||
// TODO: Consider removing this constructor
|
||||
public PaginatedList() {}
|
||||
|
||||
/**
|
||||
* Used to construct a <code>PaginatedList</code> which contains only the
|
||||
* given entity.
|
||||
*
|
||||
* @param entity the entity to include (can be <code>null</code>, which
|
||||
* indicates an empty <code>PaginatedList</code> should be created)
|
||||
*/
|
||||
public PaginatedList(E entity) {
|
||||
if (entity == null) {
|
||||
this.list = new Vector<E>();
|
||||
this.firstElement = 0;
|
||||
this.maxElements = Integer.MAX_VALUE;
|
||||
this.size = 0;
|
||||
} else {
|
||||
List<E> myList = new Vector<E>();
|
||||
myList.add(entity);
|
||||
this.list = myList;
|
||||
this.firstElement = 0;
|
||||
this.maxElements = Integer.MAX_VALUE;
|
||||
this.size = 1;
|
||||
}
|
||||
}
|
||||
|
||||
public PaginatedList(List<E> list, int firstElement, int maxElements, int size) {
|
||||
this.list = list;
|
||||
this.firstElement = firstElement;
|
||||
this.maxElements = maxElements;
|
||||
this.size = size;
|
||||
}
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
/**
|
||||
* Unsupported operation
|
||||
*
|
||||
* @param arg0 DOCUMENT ME!
|
||||
* @param arg1 DOCUMENT ME!
|
||||
*
|
||||
* @throws UnsupportedOperationException
|
||||
*
|
||||
* @see java.util.List#add(int, java.lang.Object)
|
||||
*/
|
||||
public void add(int arg0, E arg1) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Unsupported operation
|
||||
*
|
||||
* @param arg0 DOCUMENT ME!
|
||||
*
|
||||
* @return DOCUMENT ME!
|
||||
*
|
||||
* @throws UnsupportedOperationException
|
||||
*
|
||||
* @see java.util.Collection#add(java.lang.Object)
|
||||
*/
|
||||
public boolean add(E arg0) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Unsupported operation
|
||||
*
|
||||
* @param arg0 DOCUMENT ME!
|
||||
*
|
||||
* @return DOCUMENT ME!
|
||||
*
|
||||
* @throws UnsupportedOperationException
|
||||
*
|
||||
* @see java.util.Collection#addAll(java.util.Collection)
|
||||
*/
|
||||
public boolean addAll(Collection<?extends E> arg0) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Unsupported operation
|
||||
*
|
||||
* @param arg0 DOCUMENT ME!
|
||||
* @param arg1 DOCUMENT ME!
|
||||
*
|
||||
* @return DOCUMENT ME!
|
||||
*
|
||||
* @throws UnsupportedOperationException
|
||||
*
|
||||
* @see java.util.List#addAll(int, java.util.Collection)
|
||||
*/
|
||||
public boolean addAll(int arg0, Collection<?extends E> arg1) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Unsupported operation
|
||||
*
|
||||
* @throws UnsupportedOperationException
|
||||
*
|
||||
* @see java.util.Collection#clear()
|
||||
*/
|
||||
public void clear() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Unsupported operation
|
||||
*
|
||||
* @param arg0 DOCUMENT ME!
|
||||
*
|
||||
* @return DOCUMENT ME!
|
||||
*
|
||||
* @throws UnsupportedOperationException
|
||||
*
|
||||
* @see java.util.Collection#contains(java.lang.Object)
|
||||
*/
|
||||
public boolean contains(Object arg0) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Unsupported operation
|
||||
*
|
||||
* @param arg0 DOCUMENT ME!
|
||||
*
|
||||
* @return DOCUMENT ME!
|
||||
*
|
||||
* @throws UnsupportedOperationException
|
||||
*
|
||||
* @see java.util.Collection#containsAll(java.util.Collection)
|
||||
*/
|
||||
public boolean containsAll(Collection<?> arg0) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Unsupported operation
|
||||
*
|
||||
* @param arg0 DOCUMENT ME!
|
||||
*
|
||||
* @return DOCUMENT ME!
|
||||
*
|
||||
* @see java.util.List#get(int)
|
||||
*/
|
||||
public E get(int arg0) {
|
||||
return list.get(arg0);
|
||||
}
|
||||
|
||||
/**
|
||||
* First element of this page, starting at zero.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public int getFirstElement() {
|
||||
return firstElement;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the last page number, starting at 0
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public int getLastPageNumber() {
|
||||
return (size() - 1) / getMaxElements();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get list with the elements of this page.
|
||||
*
|
||||
* @return this page of the results
|
||||
*/
|
||||
public List<E> getList() {
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* Max number of elements in the page
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public int getMaxElements() {
|
||||
return maxElements;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the page number, starting at 0
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public int getPageNumber() {
|
||||
return getFirstElement() / getMaxElements();
|
||||
}
|
||||
|
||||
/**
|
||||
* Number of elements in this page
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public int getPageSize() {
|
||||
return list.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Unsupported operation
|
||||
*
|
||||
* @param arg0 DOCUMENT ME!
|
||||
*
|
||||
* @return DOCUMENT ME!
|
||||
*
|
||||
* @throws UnsupportedOperationException
|
||||
*
|
||||
* @see java.util.List#indexOf(java.lang.Object)
|
||||
*/
|
||||
public int indexOf(Object arg0) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Unsupported operation
|
||||
*
|
||||
* @return DOCUMENT ME!
|
||||
*
|
||||
* @throws UnsupportedOperationException
|
||||
*
|
||||
* @see java.util.Collection#isEmpty()
|
||||
*/
|
||||
public boolean isEmpty() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public Iterator<E> iterator() {
|
||||
return new PaginatedListIterator();
|
||||
}
|
||||
|
||||
/**
|
||||
* Unsupported operation
|
||||
*
|
||||
* @param arg0 DOCUMENT ME!
|
||||
*
|
||||
* @return DOCUMENT ME!
|
||||
*
|
||||
* @throws UnsupportedOperationException
|
||||
*
|
||||
* @see java.util.List#lastIndexOf(java.lang.Object)
|
||||
*/
|
||||
public int lastIndexOf(Object arg0) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Unsupported operation
|
||||
*
|
||||
* @return DOCUMENT ME!
|
||||
*
|
||||
* @throws UnsupportedOperationException
|
||||
*
|
||||
* @see java.util.List#listIterator()
|
||||
*/
|
||||
public ListIterator<E> listIterator() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Unsupported operation
|
||||
*
|
||||
* @param arg0 DOCUMENT ME!
|
||||
*
|
||||
* @return DOCUMENT ME!
|
||||
*
|
||||
* @throws UnsupportedOperationException
|
||||
*
|
||||
* @see java.util.List#listIterator(int)
|
||||
*/
|
||||
public ListIterator<E> listIterator(int arg0) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Unsupported operation
|
||||
*
|
||||
* @param arg0 DOCUMENT ME!
|
||||
*
|
||||
* @return DOCUMENT ME!
|
||||
*
|
||||
* @throws UnsupportedOperationException
|
||||
*
|
||||
* @see java.util.List#remove(int)
|
||||
*/
|
||||
public E remove(int arg0) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Unsupported operation
|
||||
*
|
||||
* @param arg0 DOCUMENT ME!
|
||||
*
|
||||
* @return DOCUMENT ME!
|
||||
*
|
||||
* @throws UnsupportedOperationException
|
||||
*
|
||||
* @see java.util.Collection#remove(java.lang.Object)
|
||||
*/
|
||||
public boolean remove(Object arg0) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Unsupported operation
|
||||
*
|
||||
* @param arg0 DOCUMENT ME!
|
||||
*
|
||||
* @return DOCUMENT ME!
|
||||
*
|
||||
* @throws UnsupportedOperationException
|
||||
*
|
||||
* @see java.util.Collection#removeAll(java.util.Collection)
|
||||
*/
|
||||
public boolean removeAll(Collection arg0) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Unsupported operation
|
||||
*
|
||||
* @param arg0 DOCUMENT ME!
|
||||
*
|
||||
* @return DOCUMENT ME!
|
||||
*
|
||||
* @throws UnsupportedOperationException
|
||||
*
|
||||
* @see java.util.Collection#retainAll(java.util.Collection)
|
||||
*/
|
||||
public boolean retainAll(Collection<?> arg0) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Unsupported operation
|
||||
*
|
||||
* @param arg0 DOCUMENT ME!
|
||||
* @param arg1 DOCUMENT ME!
|
||||
*
|
||||
* @return DOCUMENT ME!
|
||||
*
|
||||
* @throws UnsupportedOperationException
|
||||
*
|
||||
* @see java.util.List#set(int, java.lang.Object)
|
||||
*/
|
||||
public E set(int arg0, E arg1) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public void setFirstElement(int firstElement) {
|
||||
this.firstElement = firstElement;
|
||||
}
|
||||
|
||||
public void setList(List<E> list) {
|
||||
this.list = list;
|
||||
}
|
||||
|
||||
public void setMaxElements(int maxElements) {
|
||||
this.maxElements = maxElements;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the number of elements in all the pages
|
||||
*
|
||||
* @param size DOCUMENT ME!
|
||||
*/
|
||||
public void setSize(int size) {
|
||||
this.size = size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Number of elements in all the pages
|
||||
*
|
||||
* @see java.util.Collection#size()
|
||||
*/
|
||||
public int size() {
|
||||
return size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unsupported operation
|
||||
*
|
||||
* @param arg0 DOCUMENT ME!
|
||||
* @param arg1 DOCUMENT ME!
|
||||
*
|
||||
* @return DOCUMENT ME!
|
||||
*
|
||||
* @throws UnsupportedOperationException
|
||||
*
|
||||
* @see java.util.List#subList(int, int)
|
||||
*/
|
||||
public List<E> subList(int arg0, int arg1) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public Object[] toArray() {
|
||||
return list.toArray();
|
||||
}
|
||||
|
||||
public <T> T[] toArray(T[] arg0) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("List size when convert to array " + list.toArray().length);
|
||||
}
|
||||
|
||||
return list.toArray(arg0);
|
||||
}
|
||||
|
||||
//~ Inner Classes ==================================================================================================
|
||||
|
||||
private class PaginatedListIterator implements Iterator<E> {
|
||||
private Iterator<E> iterator;
|
||||
private int i = 0;
|
||||
|
||||
/**
|
||||
*
|
||||
* @see java.util.Iterator#hasNext()
|
||||
*/
|
||||
public boolean hasNext() {
|
||||
return i < size();
|
||||
}
|
||||
|
||||
/**
|
||||
* This method follows the rules of Iterator.next() except that it returns null when requesting an
|
||||
* element that it's not in the current page.
|
||||
*
|
||||
* @see java.util.Iterator#next()
|
||||
*/
|
||||
public E next() {
|
||||
if (i == getFirstElement()) {
|
||||
iterator = getList().iterator();
|
||||
}
|
||||
|
||||
if ((i >= getFirstElement()) && (i < (getFirstElement() + getMaxElements()))) {
|
||||
i++;
|
||||
|
||||
return iterator.next();
|
||||
}
|
||||
|
||||
if (hasNext()) {
|
||||
i++;
|
||||
|
||||
return null;
|
||||
} else {
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unsupported operation
|
||||
*
|
||||
* @throws UnsupportedOperationException
|
||||
*
|
||||
* @see java.util.Iterator#remove()
|
||||
*/
|
||||
public void remove() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,6 +0,0 @@
|
|||
<html>
|
||||
<body>
|
||||
<p>Provides the base of a data access object (DAO) persistence layer.</p>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,269 +0,0 @@
|
|||
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* Licensed 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.acegisecurity.domain.hibernate;
|
||||
|
||||
import org.acegisecurity.domain.PersistableEntity;
|
||||
import org.acegisecurity.domain.dao.Dao;
|
||||
import org.acegisecurity.domain.dao.PaginatedList;
|
||||
import org.acegisecurity.domain.util.GenericsUtils;
|
||||
|
||||
import org.hibernate.Criteria;
|
||||
import org.hibernate.EntityMode;
|
||||
import org.hibernate.Hibernate;
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.SessionFactory;
|
||||
|
||||
import org.hibernate.criterion.Expression;
|
||||
import org.hibernate.criterion.Order;
|
||||
|
||||
import org.hibernate.metadata.ClassMetadata;
|
||||
|
||||
import org.hibernate.type.Type;
|
||||
|
||||
import org.springframework.orm.hibernate3.HibernateCallback;
|
||||
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
* Generics supporting {@link Dao} implementation that uses Hibernate 3 for persistence.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @author Matthew Porter
|
||||
* @version $Id$
|
||||
*
|
||||
* @param <E> DOCUMENT ME!
|
||||
*/
|
||||
public class DaoHibernate<E extends PersistableEntity> extends HibernateDaoSupport implements Dao<E> {
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
/** The class that this instance provides services for */
|
||||
private Class supportsClass;
|
||||
|
||||
//~ Constructors ===================================================================================================
|
||||
|
||||
public DaoHibernate(SessionFactory sessionFactory) {
|
||||
Assert.notNull(sessionFactory, "Non-null Hibernate SessionFactory must be expressed as a constructor argument");
|
||||
super.setSessionFactory(sessionFactory);
|
||||
this.supportsClass = GenericsUtils.getGeneric(getClass());
|
||||
Assert.notNull(this.supportsClass, "Could not determine the generics type");
|
||||
}
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
public void create(E value) {
|
||||
Assert.notNull(value);
|
||||
super.getHibernateTemplate().save(value);
|
||||
}
|
||||
|
||||
public void delete(E value) {
|
||||
Assert.notNull(value);
|
||||
super.getHibernateTemplate().delete(value);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public List<E> findAll() {
|
||||
return super.getHibernateTemplate().loadAll(supportsClass);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public List<E> findId(Collection<Serializable> ids) {
|
||||
Assert.notNull(ids, "Collection of IDs cannot be null");
|
||||
Assert.notEmpty(ids, "There must be some values in the Collection list");
|
||||
|
||||
return (List) super.getHibernateTemplate().execute(getFindByIdCallback(ids));
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a <code>HibernateCallback</code> that will load a list of objects by a <code>Collection</code>
|
||||
* of identities.
|
||||
*
|
||||
* @param ids collection of identities to be loaded
|
||||
*
|
||||
* @return a <code>List</code> containing the matching objects
|
||||
*/
|
||||
private HibernateCallback getFindByIdCallback(final Collection<Serializable> ids) {
|
||||
return new HibernateCallback() {
|
||||
public Object doInHibernate(Session session)
|
||||
throws HibernateException {
|
||||
Criteria criteria = session.createCriteria(supportsClass);
|
||||
|
||||
ClassMetadata classMetadata = getSessionFactory().getClassMetadata(supportsClass);
|
||||
|
||||
String idPropertyName = classMetadata.getIdentifierPropertyName();
|
||||
criteria.add(Expression.in(idPropertyName, ids));
|
||||
|
||||
return criteria.list();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a new <code>HibernateCallback</code> for finding objects by a bean property values, paginating the
|
||||
* results. Properties with null values and collections and empty Strings are ignored, as is any property with the
|
||||
* "version" name. If the property is mapped as String find a partial match, otherwise find by exact match.
|
||||
*
|
||||
* @param whichClass the class (and subclasses) which results will be limited to including
|
||||
* @param bean bean with the values of the parameters
|
||||
* @param firstElement the first result, numbered from 0
|
||||
* @param count the maximum number of results
|
||||
* @param order DOCUMENT ME!
|
||||
*
|
||||
* @return a PaginatedList containing the requested objects
|
||||
*/
|
||||
private HibernateCallback getFindByValueCallback(final Class whichClass, final Object bean, final int firstElement,
|
||||
final int count, final Order order) {
|
||||
return new HibernateCallback() {
|
||||
@SuppressWarnings("unchecked")
|
||||
public Object doInHibernate(Session session)
|
||||
throws HibernateException {
|
||||
int paramCount = 0;
|
||||
|
||||
StringBuffer queryString = new StringBuffer("from ").append(bean.getClass().getName())
|
||||
.append(" as queryTarget");
|
||||
|
||||
ClassMetadata classMetadata = getSessionFactory().getClassMetadata(bean.getClass());
|
||||
|
||||
Assert.notNull(classMetadata,
|
||||
"ClassMetadata for " + bean.getClass()
|
||||
+ " unavailable from Hibernate - have you mapped this class against the SessionFactory?");
|
||||
|
||||
/* get persistent properties */
|
||||
Type[] propertyTypes = classMetadata.getPropertyTypes();
|
||||
String[] propertyNames = classMetadata.getPropertyNames();
|
||||
|
||||
/* for each persistent property of the bean */
|
||||
for (int i = 0; i < propertyNames.length; i++) {
|
||||
String name = propertyNames[i];
|
||||
|
||||
// TODO: Check if EntityMode.POJO appropriate
|
||||
Object value = classMetadata.getPropertyValue(bean, name, EntityMode.POJO);
|
||||
|
||||
if (value == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// ignore empty Strings
|
||||
if (value instanceof String) {
|
||||
String string = (String) value;
|
||||
|
||||
if ("".equals(string)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// ignore any collections
|
||||
if (propertyTypes[i].isCollectionType()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (name.equals("version")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Type type = classMetadata.getPropertyType(name);
|
||||
|
||||
if (type.equals(Hibernate.STRING)) {
|
||||
// if the property is mapped as String, find partial match
|
||||
if (paramCount == 0) {
|
||||
queryString.append(" where ");
|
||||
} else {
|
||||
queryString.append(" and ");
|
||||
}
|
||||
|
||||
paramCount++;
|
||||
queryString.append("lower(queryTarget.").append(name)
|
||||
.append(") like '%" + value.toString().toLowerCase() + "%'");
|
||||
} else {
|
||||
// find exact match
|
||||
if (paramCount == 0) {
|
||||
queryString.append(" where ");
|
||||
} else {
|
||||
queryString.append(" and ");
|
||||
}
|
||||
|
||||
paramCount++;
|
||||
queryString.append("queryTarget.").append(name).append(" = " + value);
|
||||
}
|
||||
}
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(queryString.toString());
|
||||
}
|
||||
|
||||
// Determine number of rows
|
||||
org.hibernate.Query countQuery = session.createQuery("select count(*) " + queryString.toString());
|
||||
int size = ((Integer) countQuery.iterate().next()).intValue();
|
||||
|
||||
// Obtain requested page of query
|
||||
org.hibernate.Query query = session.createQuery(queryString.toString());
|
||||
query.setMaxResults(count);
|
||||
query.setFirstResult(firstElement);
|
||||
|
||||
return new PaginatedList(query.list(), firstElement, count, size);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public E readId(Serializable id) {
|
||||
Assert.notNull(id);
|
||||
|
||||
return (E) getHibernateTemplate().load(supportsClass, id);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public PaginatedList<E> scroll(E value, int firstElement, int maxElements, String orderByAsc) {
|
||||
validateScrollMethod(value, firstElement, maxElements, orderByAsc);
|
||||
|
||||
return (PaginatedList) super.getHibernateTemplate()
|
||||
.execute(getFindByValueCallback(value.getClass(), value, firstElement, maxElements,
|
||||
Order.asc(orderByAsc)));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public PaginatedList<E> scrollWithSubclasses(E value, int firstElement, int maxElements, String orderByAsc) {
|
||||
validateScrollMethod(value, firstElement, maxElements, orderByAsc);
|
||||
|
||||
return (PaginatedList) super.getHibernateTemplate()
|
||||
.execute(getFindByValueCallback(this.supportsClass, value, firstElement,
|
||||
maxElements, Order.asc(orderByAsc)));
|
||||
}
|
||||
|
||||
public boolean supports(Class clazz) {
|
||||
Assert.notNull(clazz);
|
||||
|
||||
return this.supportsClass.equals(clazz);
|
||||
}
|
||||
|
||||
public void update(E value) {
|
||||
Assert.notNull(value);
|
||||
super.getHibernateTemplate().update(value);
|
||||
}
|
||||
|
||||
private void validateScrollMethod(E value, int firstElement, int MaxElements, String orderByAsc) {
|
||||
Assert.notNull(value);
|
||||
Assert.hasText(orderByAsc, "An orderByAsc is required (why not use your identity property?)");
|
||||
Assert.isInstanceOf(this.supportsClass, value, "Can only scroll with values this DAO supports");
|
||||
}
|
||||
}
|
|
@ -1,124 +0,0 @@
|
|||
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* Licensed 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.acegisecurity.domain.hibernate;
|
||||
|
||||
import org.acegisecurity.domain.util.GenericsUtils;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
|
||||
import org.hibernate.usertype.UserType;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Types;
|
||||
|
||||
|
||||
/**
|
||||
* Java 1.5 <code>enum</code>eration compatible Hibernate 3 <code>UserType</code>.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*
|
||||
* @param <E> DOCUMENT ME!
|
||||
*/
|
||||
public class EnumUserType<E extends Enum<E>> implements UserType {
|
||||
//~ Static fields/initializers =====================================================================================
|
||||
|
||||
private static final int[] SQL_TYPES = {Types.VARCHAR};
|
||||
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
private Class<E> clazz = null;
|
||||
|
||||
//~ Constructors ===================================================================================================
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
protected EnumUserType() {
|
||||
this.clazz = GenericsUtils.getGeneric(getClass());
|
||||
}
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
public Object assemble(Serializable cached, Object owner)
|
||||
throws HibernateException {
|
||||
return cached;
|
||||
}
|
||||
|
||||
public Object deepCopy(Object value) throws HibernateException {
|
||||
return value;
|
||||
}
|
||||
|
||||
public Serializable disassemble(Object value) throws HibernateException {
|
||||
return (Serializable) value;
|
||||
}
|
||||
|
||||
public boolean equals(Object x, Object y) throws HibernateException {
|
||||
if (x == y) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ((null == x) || (null == y)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return x.equals(y);
|
||||
}
|
||||
|
||||
public int hashCode(Object x) throws HibernateException {
|
||||
return x.hashCode();
|
||||
}
|
||||
|
||||
public boolean isMutable() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public Object nullSafeGet(ResultSet resultSet, String[] names, Object owner)
|
||||
throws HibernateException, SQLException {
|
||||
String name = resultSet.getString(names[0]);
|
||||
E result = null;
|
||||
|
||||
if (!resultSet.wasNull()) {
|
||||
result = Enum.valueOf(clazz, name);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public void nullSafeSet(PreparedStatement preparedStatement, Object value, int index)
|
||||
throws HibernateException, SQLException {
|
||||
if (null == value) {
|
||||
preparedStatement.setNull(index, Types.VARCHAR);
|
||||
} else {
|
||||
preparedStatement.setString(index, ((Enum) value).name());
|
||||
}
|
||||
}
|
||||
|
||||
public Object replace(Object original, Object target, Object owner)
|
||||
throws HibernateException {
|
||||
return original;
|
||||
}
|
||||
|
||||
public Class returnedClass() {
|
||||
return clazz;
|
||||
}
|
||||
|
||||
public int[] sqlTypes() {
|
||||
return SQL_TYPES;
|
||||
}
|
||||
}
|
|
@ -1,143 +0,0 @@
|
|||
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* Licensed 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.acegisecurity.domain.hibernate;
|
||||
|
||||
import org.acegisecurity.domain.validation.IntrospectionManager;
|
||||
import org.acegisecurity.domain.validation.ValidationRegistryManager;
|
||||
|
||||
import org.hibernate.EntityMode;
|
||||
import org.hibernate.Hibernate;
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.SessionFactory;
|
||||
|
||||
import org.hibernate.metadata.ClassMetadata;
|
||||
|
||||
import org.hibernate.type.Type;
|
||||
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
|
||||
import org.springframework.orm.hibernate3.HibernateSystemException;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
/**
|
||||
* {@link IntrospectionManager} that uses Hibernate metadata to locate children.<p>Add children objects are added
|
||||
* to the <code>List</code> of children objects to validate, irrespective of whether a save/update/delete operation
|
||||
* will cascade to them. This is not a perfect solution, but addresses most real-world validation requirements (you
|
||||
* can always implement your own <code>IntrospectionManager</code> if you prefer).</p>
|
||||
* <p>This implementation only adds properties of a parent object that have a Hibernate {@link
|
||||
* net.sf.hibernate.type.Type} that indicates it is an object type (ie {@link
|
||||
* net.sf.hibernate.type.Type#isObjectType()}).</p>
|
||||
*
|
||||
* @author Matthew Porter
|
||||
* @author Ben Alex
|
||||
*/
|
||||
public class IntrospectionManagerHibernate implements IntrospectionManager, InitializingBean {
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
private ValidationRegistryManager validationRegistryManager;
|
||||
private SessionFactory[] sessionFactories;
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
Assert.notNull(validationRegistryManager, "ValidationRegistryManager is required");
|
||||
Assert.notNull(sessionFactories, "SessionFactories are required");
|
||||
Assert.notEmpty(sessionFactories, "SessionFactories are required");
|
||||
|
||||
// Eagerly pre-register Validators for all Hibernate metadata-defined classes
|
||||
for (int i = 0; i < sessionFactories.length; i++) {
|
||||
Map<String, ClassMetadata> metadataMap = this.sessionFactories[i].getAllClassMetadata();
|
||||
Collection<String> mappedClasses = metadataMap.keySet();
|
||||
|
||||
for (Iterator<String> iter = mappedClasses.iterator(); iter.hasNext();) {
|
||||
String className = iter.next();
|
||||
this.validationRegistryManager.findValidator(Class.forName(className));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private ClassMetadata findMetadata(Class clazz) throws HibernateSystemException {
|
||||
for (int i = 0; i < sessionFactories.length; i++) {
|
||||
ClassMetadata result = sessionFactories[i].getClassMetadata(clazz);
|
||||
|
||||
if (result != null) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public SessionFactory[] getSessionFactories() {
|
||||
return this.sessionFactories;
|
||||
}
|
||||
|
||||
public ValidationRegistryManager getValidationRegistryManager() {
|
||||
return validationRegistryManager;
|
||||
}
|
||||
|
||||
public void obtainImmediateChildren(Object parentObject, List<Object> allObjects) {
|
||||
Assert.notNull(parentObject, "Violation of interface contract: parentObject null");
|
||||
Assert.notNull(allObjects, "Violation of interface contract: allObjects null");
|
||||
|
||||
ClassMetadata classMetadata = null;
|
||||
|
||||
try {
|
||||
classMetadata = findMetadata(parentObject.getClass());
|
||||
|
||||
if (classMetadata != null) {
|
||||
String[] propertyNames = classMetadata.getPropertyNames();
|
||||
|
||||
for (int i = 0; i < propertyNames.length; i++) {
|
||||
Type propertyType = classMetadata.getPropertyType(propertyNames[i]);
|
||||
|
||||
// Add this property to the List of Objects to validate
|
||||
// only if a Validator is registered for that Object AND
|
||||
// the object is initialized (ie not lazy loaded)
|
||||
if (this.validationRegistryManager.findValidator(propertyType.getReturnedClass()) != null) {
|
||||
Object childObject = classMetadata.getPropertyValue(parentObject, propertyNames[i],
|
||||
EntityMode.POJO);
|
||||
|
||||
if ((childObject != null) && Hibernate.isInitialized(childObject)) {
|
||||
if (childObject instanceof Collection) {
|
||||
allObjects.addAll((Collection) childObject);
|
||||
} else {
|
||||
allObjects.add(childObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (HibernateException he) {
|
||||
throw new HibernateSystemException(he);
|
||||
}
|
||||
}
|
||||
|
||||
public void setSessionFactories(SessionFactory[] sessionFactorys) {
|
||||
this.sessionFactories = sessionFactorys;
|
||||
}
|
||||
|
||||
public void setValidationRegistryManager(ValidationRegistryManager validationRegistryManager) {
|
||||
this.validationRegistryManager = validationRegistryManager;
|
||||
}
|
||||
}
|
|
@ -1,6 +0,0 @@
|
|||
<html>
|
||||
<body>
|
||||
<p>Hibernate-specific implementations of the domain subproject interfaces.</p>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,57 +0,0 @@
|
|||
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* Licensed 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.acegisecurity.domain.impl;
|
||||
|
||||
import org.acegisecurity.domain.PersistableEntity;
|
||||
|
||||
|
||||
/**
|
||||
* An abstract implementation of {@link org.acegisecurity.domain.PersistableEntity}.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public abstract class AbstractPersistableEntity extends BusinessObject implements PersistableEntity {
|
||||
//~ Static fields/initializers =====================================================================================
|
||||
|
||||
public static final int STARTING_VERSION = 0;
|
||||
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
private int version = STARTING_VERSION;
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
/**
|
||||
* Returns the version number, which should be managed by the persistence layer.<p>Initially all
|
||||
* <code>PersistableEntity</code>s will commence with the version number defined by {@link #STARTING_VERSION}.</p>
|
||||
*
|
||||
* @return the version
|
||||
*/
|
||||
public int getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether this persistable entity has been persisted yet. Determine based on whether the {@link
|
||||
* #getInternalId()} returns <code>null</code> or a non-<code>null</code> value.
|
||||
*
|
||||
* @return <code>true</code> if the instance has not been persisted, <code>false</code> otherwise
|
||||
*/
|
||||
public boolean isNew() {
|
||||
return (getInternalId() == null);
|
||||
}
|
||||
}
|
|
@ -1,73 +0,0 @@
|
|||
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* Licensed 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.acegisecurity.domain.impl;
|
||||
|
||||
import org.acegisecurity.domain.util.ReflectionToStringBuilder;
|
||||
|
||||
import org.apache.commons.beanutils.BeanUtils;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
|
||||
/**
|
||||
* A business domain object.<p>Only minimal convenience methods are provided by <code>BusinessObject</code>. Whilst
|
||||
* many other methods could easily be offered (and overridden on an as-required basis) it is felt the default
|
||||
* behaviour of {@link java.lang.Object} is widely understood and an appropriate default.</p>
|
||||
*
|
||||
* @author Carlos Sanchez
|
||||
* @author Ben Alex
|
||||
* @author Matthew Porter
|
||||
* @version $Id$
|
||||
*/
|
||||
public abstract class BusinessObject implements Serializable, Cloneable {
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
protected final transient Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
/**
|
||||
* Swallow cloning.<p>This method delegates to BeanUtils.cloneBean(). Please note that this class uses
|
||||
* serialization to achieve a clone, so this may represent a performance issue in certain applications. In such
|
||||
* circumstances you should override this method and provide alternative cloning logic.</p>
|
||||
*
|
||||
* @return a clone of the current instance
|
||||
*
|
||||
* @throws CloneNotSupportedException if there are any problems with swallow cloning
|
||||
*
|
||||
* @see java.lang.Object#clone()
|
||||
* @see BeanUtils#cloneBean(Object)
|
||||
*/
|
||||
public Object clone() throws CloneNotSupportedException {
|
||||
try {
|
||||
return BeanUtils.cloneBean(this);
|
||||
} catch (Exception e) {
|
||||
logger.error(e);
|
||||
throw new CloneNotSupportedException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delegates to {@link CollectionIgnoringReflectionToStringBuilder}.
|
||||
*
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
public String toString() {
|
||||
return new ReflectionToStringBuilder(this).toString();
|
||||
}
|
||||
}
|
|
@ -1,51 +0,0 @@
|
|||
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* Licensed 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.acegisecurity.domain.impl;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
|
||||
/**
|
||||
* A persistable entity that uses a <code>Integer</code> based identity.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public abstract class PersistableEntityInteger extends AbstractPersistableEntity {
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
private Integer id;
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
/**
|
||||
* Obtains the persistence identity of this instance.
|
||||
*
|
||||
* @return DOCUMENT ME!
|
||||
*/
|
||||
public Integer getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Required solely because Hibernate
|
||||
*
|
||||
* @return DOCUMENT ME!
|
||||
*/
|
||||
public Serializable getInternalId() {
|
||||
return this.id;
|
||||
}
|
||||
}
|
|
@ -1,51 +0,0 @@
|
|||
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* Licensed 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.acegisecurity.domain.impl;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
|
||||
/**
|
||||
* A persistable entity that uses a <code>Long</code> based identity.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public abstract class PersistableEntityLong extends AbstractPersistableEntity {
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
private Long id;
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
/**
|
||||
* Obtains the persistence identity of this instance.
|
||||
*
|
||||
* @return DOCUMENT ME!
|
||||
*/
|
||||
public Long getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Required solely because Hibernate
|
||||
*
|
||||
* @return DOCUMENT ME!
|
||||
*/
|
||||
public Serializable getInternalId() {
|
||||
return this.id;
|
||||
}
|
||||
}
|
|
@ -1,29 +0,0 @@
|
|||
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* Licensed 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.acegisecurity.domain.impl;
|
||||
|
||||
/**
|
||||
* A <i>value object</i>, which means a persistable business object that does not have its own persistence
|
||||
* identity.<p>Every value object belongs to a single {@link
|
||||
* org.acegisecurity.domain.impl.AbstractPersistableEntity}. This is necessary so that the value object has some sort
|
||||
* of persistence relationship/ownership.</p>
|
||||
* <P>In addition, a value object cannot be referenced from more than one <code>PersistableEntity</code>. Use a
|
||||
* <code>PersistableEntity</code> instead of a <code>PersistableValue</code> if this is a design constraint.</p>
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public abstract class PersistableValue extends BusinessObject {}
|
|
@ -1,7 +0,0 @@
|
|||
<html>
|
||||
<body>
|
||||
<p>Convenient domain object abstract classes, although none are mandatory/required by
|
||||
other packages in this project.</p>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
<html>
|
||||
<body>
|
||||
<p>Provides tools to assist develop rich domain object models.</p>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,151 +0,0 @@
|
|||
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* Licensed 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.acegisecurity.domain.service;
|
||||
|
||||
import org.acegisecurity.domain.PersistableEntity;
|
||||
import org.acegisecurity.domain.dao.PaginatedList;
|
||||
|
||||
import org.springframework.dao.DataAccessException;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
* Provides fundamental services layer capabilities for a single concrete {@link
|
||||
* PersistableEntity}, using JDK 1.5 generics.
|
||||
*
|
||||
* <P>
|
||||
* A design decision was to rely on by-reference calling semantics typical of
|
||||
* recommended same-JVM (colocated) deployment environments. If you are using
|
||||
* remoting you may need to provide a remoting facade that returns the updated
|
||||
* object to the client.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* It is not envisioned that this interface will provide <b>all</b> services layer
|
||||
* functions. The significant value of a services layer is the value-add beyond
|
||||
* simply fronting the DAO. The type of value-adds
|
||||
* expected to be provided by a services layer include incrementing business
|
||||
* identifiers (eg an invoice number); generating messages for logging/audit
|
||||
* purposes (thus such messages are at a business transaction level of granularity,
|
||||
* instead of DAO/persistence granularity where the overall context of the
|
||||
* the message becomes unclear); updating related domain objects via
|
||||
* their respective services layer beans (eg an invoice services layer bean
|
||||
* would call the general journal services layer bean to create the accrual
|
||||
* accounting entries); producing messages (eg notify another system the invoice
|
||||
* was created or email the customer via SMTP); provide a layer to locate transaction
|
||||
* and security configuration etc.
|
||||
* </p>
|
||||
*
|
||||
* <P>
|
||||
* A single <code>ImmutableManager</code> implementation will typically exist for each
|
||||
* {@link org.acegisecurity.domain.PersistableEntity}, particularly given
|
||||
* a <code>PersistableEntity</code> is allowed to manage multiple
|
||||
* {@link org.acegisecurity.domain.impl.PersistableValue}s.
|
||||
* The particular <code>PersistableEntity</code> an implementation supports
|
||||
* will be expressed by the {@link #supports(Class)} method.
|
||||
* </p>
|
||||
*
|
||||
* <p>No other part of the Domain subproject relies on this interface. If
|
||||
* you would prefer to write your own services layer interfaces from scratch,
|
||||
* this is not a problem at all.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public interface ImmutableManager<E extends PersistableEntity> {
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
/**
|
||||
* Return all persistent instances, including subclasses.
|
||||
*
|
||||
* @return all persistence instances (an empty <code>List</code> will be returned if no matches are found)
|
||||
*
|
||||
* @throws DataAccessException DOCUMENT ME!
|
||||
*/
|
||||
public List<E> findAll() throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Find a <code>List</code> of <code>PersistableEntity</code>s, searched by their identifiers.
|
||||
*
|
||||
* @param ids collection of identifiers to locate
|
||||
*
|
||||
* @return the values with those identifiers (an empty <code>List</code> will be returned if no matches are found)
|
||||
*
|
||||
* @throws DataAccessException DOCUMENT ME!
|
||||
*/
|
||||
public List<E> findId(Collection<Serializable> ids)
|
||||
throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Load a persistent instance by its identifier, although some properties may be lazy loaded depending on
|
||||
* the underlying DAO implementation and/or persistence engine mapping document.
|
||||
*
|
||||
* @param id the identifier of the persistent instance desired to be retrieved
|
||||
*
|
||||
* @return the request item, or <code>null</code> if not found
|
||||
*
|
||||
* @throws DataAccessException DOCUMENT ME!
|
||||
*/
|
||||
public E readId(Serializable id) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Find persistent instances with properties matching those of the passed <code>PersistableEntity</code>.<P>Persistent
|
||||
* instances are matched on the basis of query by example. Properties whose value is <code>null</code>, empty
|
||||
* <code>String</code>s, and any <code>Collection</code>s are ignored in the query by example evaluation.</p>
|
||||
*
|
||||
* @param value parameters to filter on (the class of this object will be added to the filter)
|
||||
* @param firstElement the first result (start at zero to obtain all results)
|
||||
* @param maxElements the maximum number of results desired for this page of the result set
|
||||
*
|
||||
* @return the requested page of the result list (a properly formed <code>PaginatedList</code> is returned if no
|
||||
* results match)
|
||||
*
|
||||
* @throws DataAccessException DOCUMENT ME!
|
||||
*/
|
||||
public PaginatedList<E> scroll(E value, int firstElement, int maxElements)
|
||||
throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Find persistent instances with properties matching those of the passed <code>PersistableEntity</code>,
|
||||
* ignoring the class of the passed <code>PersistableEntity</code> (useful if you pass a superclass, as you want
|
||||
* to find all subclass instances which match).
|
||||
*
|
||||
* @param value parameters to filter on (the class of this object will NOT be added to the filter)
|
||||
* @param firstElement the first result (start at zero to obtain all results)
|
||||
* @param maxElements the maximum number of results desired for this page of the result set
|
||||
*
|
||||
* @return the requested page of the result list (a properly formed <code>PaginatedList</code> is returned if no
|
||||
* results match)
|
||||
*
|
||||
* @throws DataAccessException DOCUMENT ME!
|
||||
*/
|
||||
public PaginatedList<E> scrollWithSubclasses(E value, int firstElement, int maxElements)
|
||||
throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Indicates whether the DAO instance provides persistence services for the specified class.
|
||||
*
|
||||
* @param clazz to test, which should be an implementation of <code>PersistableEntity</code>
|
||||
*
|
||||
* @return <code>true</code> or <code>false</code>, indicating whether or not the passed class is supported by this
|
||||
* DAO instance
|
||||
*/
|
||||
public boolean supports(Class clazz);
|
||||
}
|
|
@ -1,82 +0,0 @@
|
|||
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* Licensed 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.acegisecurity.domain.service;
|
||||
|
||||
import org.acegisecurity.domain.PersistableEntity;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.beans.PropertyEditorSupport;
|
||||
|
||||
|
||||
/**
|
||||
* Converts between a PersistableEntity's internal ID (expressed as a String and the corresponding
|
||||
* PersistableEntity sourced from an ImmutableManager).
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class ImmutableManagerEditor extends PropertyEditorSupport {
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
private ImmutableManager immutableManager;
|
||||
protected final transient Log log = LogFactory.getLog(getClass());
|
||||
private final boolean fallbackToNull;
|
||||
|
||||
//~ Constructors ===================================================================================================
|
||||
|
||||
public ImmutableManagerEditor(ImmutableManager immutableManager, boolean fallbackToNull) {
|
||||
Assert.notNull(immutableManager, "ImmutableManager required");
|
||||
this.immutableManager = immutableManager;
|
||||
this.fallbackToNull = fallbackToNull;
|
||||
}
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
public String getAsText() {
|
||||
String result = null;
|
||||
|
||||
if (getValue() != null) {
|
||||
result = ((PersistableEntity) getValue()).getInternalId().toString();
|
||||
}
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Property Editor returning: " + result);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public void setAsText(String text) throws IllegalArgumentException {
|
||||
if (this.fallbackToNull && !StringUtils.hasText(text)) {
|
||||
// treat empty String as null value
|
||||
setValue(null);
|
||||
} else {
|
||||
Long id = new Long(text);
|
||||
PersistableEntity value = immutableManager.readId(id);
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Property Editor converted '" + text + "' to object: " + value);
|
||||
}
|
||||
|
||||
setValue(value);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,113 +0,0 @@
|
|||
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* Licensed 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.acegisecurity.domain.service;
|
||||
|
||||
import org.acegisecurity.domain.PersistableEntity;
|
||||
import org.acegisecurity.domain.dao.Dao;
|
||||
import org.acegisecurity.domain.dao.PaginatedList;
|
||||
import org.acegisecurity.domain.util.GenericsUtils;
|
||||
|
||||
import org.springframework.context.support.ApplicationObjectSupport;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
* Base {@link ImmutableManager} implementation.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*
|
||||
* @param <E> DOCUMENT ME!
|
||||
*/
|
||||
public class ImmutableManagerImpl<E extends PersistableEntity> extends ApplicationObjectSupport
|
||||
implements ImmutableManager<E> {
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
/** The class that this instance provides services for */
|
||||
private Class supportsClass;
|
||||
protected Dao<E> dao;
|
||||
|
||||
//~ Constructors ===================================================================================================
|
||||
|
||||
public ImmutableManagerImpl(Dao<E> dao) {
|
||||
// work out what domain object we support
|
||||
this.supportsClass = GenericsUtils.getGeneric(getClass());
|
||||
Assert.notNull(this.supportsClass, "Could not determine the generics type");
|
||||
Assert.isTrue(PersistableEntity.class.isAssignableFrom(supportsClass),
|
||||
"supportClass is not an implementation of PersistableEntity");
|
||||
|
||||
// store the DAO and check it also supports our domain object type
|
||||
Assert.notNull(dao,
|
||||
"Non-null DAO (that supports the same domain object class as this services layer) is required as a constructor argument");
|
||||
Assert.isTrue(dao.supports(supportsClass), "Dao '" + dao + "' does not support '" + supportsClass + "'");
|
||||
this.dao = dao;
|
||||
}
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
public List<E> findAll() {
|
||||
return dao.findAll();
|
||||
}
|
||||
|
||||
public List<E> findId(Collection<Serializable> ids) {
|
||||
Assert.notNull(ids, "Collection of IDs cannot be null");
|
||||
Assert.notEmpty(ids, "There must be some values in the Collection list");
|
||||
|
||||
return dao.findId(ids);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
DOCUMENT ME!
|
||||
*
|
||||
* @return the sort order column to be used by default by the scroll methods
|
||||
*/
|
||||
protected String getDefaultSortOrder() {
|
||||
return "id";
|
||||
}
|
||||
|
||||
public E readId(Serializable id) {
|
||||
Assert.notNull(id);
|
||||
|
||||
return dao.readId(id);
|
||||
}
|
||||
|
||||
public PaginatedList<E> scroll(E value, int firstElement, int maxElements) {
|
||||
Assert.notNull(value);
|
||||
Assert.isInstanceOf(this.supportsClass, value, "Can only scroll with values this manager supports");
|
||||
|
||||
return dao.scroll(value, firstElement, maxElements, getDefaultSortOrder());
|
||||
}
|
||||
|
||||
public PaginatedList<E> scrollWithSubclasses(E value, int firstElement, int maxElements) {
|
||||
Assert.notNull(value);
|
||||
Assert.isInstanceOf(this.supportsClass, value, "Can only scroll with values this manager supports");
|
||||
|
||||
return dao.scrollWithSubclasses(value, firstElement, maxElements, getDefaultSortOrder());
|
||||
}
|
||||
|
||||
public boolean supports(Class clazz) {
|
||||
Assert.notNull(clazz);
|
||||
|
||||
return this.supportsClass.equals(clazz);
|
||||
}
|
||||
}
|
|
@ -1,164 +0,0 @@
|
|||
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* Licensed 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.acegisecurity.domain.util;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.SortedMap;
|
||||
import java.util.SortedSet;
|
||||
import java.util.TreeMap;
|
||||
import java.util.TreeSet;
|
||||
|
||||
|
||||
/**
|
||||
* Some utility methods to use <code>Collection</code>s.
|
||||
*
|
||||
* @author Carlos Sanchez
|
||||
* @version $Id$
|
||||
*/
|
||||
public class CollectionUtils {
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
/**
|
||||
* Add an object to a <code>Set</code> and return the result.
|
||||
*
|
||||
* @param <E> DOCUMENT ME!
|
||||
* @param set
|
||||
* @param object
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static <E> Set<E> add(Set<E> set, E object) {
|
||||
set.add(object);
|
||||
|
||||
return set;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an object to a <code>List</code> and return the result.
|
||||
*
|
||||
* @param <E> DOCUMENT ME!
|
||||
* @param list
|
||||
* @param object
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static <E> List<E> add(List<E> list, E object) {
|
||||
list.add(object);
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clone a Collection copying all its elements to a new one. If map is <code>null</code> return
|
||||
* <code>null</code>.
|
||||
*
|
||||
* @param <E> DOCUMENT ME!
|
||||
* @param collection
|
||||
*
|
||||
* @return
|
||||
*
|
||||
* @throws IllegalArgumentException DOCUMENT ME!
|
||||
*/
|
||||
public static <E> Collection<E> clone(Collection<E> collection) {
|
||||
if (collection == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Class clazz = collection.getClass();
|
||||
Collection<E> clone = null;
|
||||
|
||||
if (List.class.isAssignableFrom(clazz)) {
|
||||
clone = new ArrayList<E>(collection);
|
||||
} else if (SortedSet.class.isAssignableFrom(clazz)) {
|
||||
clone = new TreeSet<E>(collection);
|
||||
} else if (Set.class.isAssignableFrom(clazz)) {
|
||||
clone = new HashSet<E>(collection);
|
||||
} else {
|
||||
throw new IllegalArgumentException("Unknown collection class: " + clazz);
|
||||
}
|
||||
|
||||
return clone;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clone a <code>Map</code> copying all its elements to a new one. If the passed argument is
|
||||
* <code>null</code>, the method will return <code>null</code>.
|
||||
*
|
||||
* @param <K> DOCUMENT ME!
|
||||
* @param <V> DOCUMENT ME!
|
||||
* @param map to copy
|
||||
*
|
||||
* @return a copy of the <code>Map</code> passed as an argument
|
||||
*
|
||||
* @throws IllegalArgumentException if the <code>Map</code> implementation is not supported by this method
|
||||
*/
|
||||
public static <K, V> Map<K, V> clone(Map<K, V> map) {
|
||||
if (map == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Class clazz = map.getClass();
|
||||
Map<K, V> clone = null;
|
||||
|
||||
if (SortedMap.class.isAssignableFrom(clazz)) {
|
||||
clone = new TreeMap<K, V>(map);
|
||||
} else if (Map.class.isAssignableFrom(clazz)) {
|
||||
clone = new HashMap<K, V>(map);
|
||||
} else {
|
||||
throw new IllegalArgumentException("Unknown map class: " + clazz);
|
||||
}
|
||||
|
||||
return clone;
|
||||
}
|
||||
|
||||
public static boolean isCollection(Class theClass) {
|
||||
return Collection.class.isAssignableFrom(theClass);
|
||||
}
|
||||
|
||||
public static boolean isMap(Class theClass) {
|
||||
return Map.class.isAssignableFrom(theClass);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a <code>List</code> (actually an {@link ArrayList}) with only that object.
|
||||
*
|
||||
* @param <E> DOCUMENT ME!
|
||||
* @param object
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static <E> List<E> newList(E object) {
|
||||
return add(new ArrayList<E>(1), object);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a <code>Set</code> (actually a {@link HashSet}) with only that object.
|
||||
*
|
||||
* @param <E> DOCUMENT ME!
|
||||
* @param object
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static <E> Set<E> newSet(E object) {
|
||||
return add(new HashSet<E>(), object);
|
||||
}
|
||||
}
|
|
@ -1,93 +0,0 @@
|
|||
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* Licensed 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.acegisecurity.domain.util;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.beans.PropertyEditorSupport;
|
||||
|
||||
|
||||
/**
|
||||
* DOCUMENT ME!
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class EnumEditor extends PropertyEditorSupport {
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
private final Class<?extends Enum> enumClass;
|
||||
protected final transient Log log = LogFactory.getLog(getClass());
|
||||
private final boolean fallbackToNull;
|
||||
|
||||
//~ Constructors ===================================================================================================
|
||||
|
||||
/**
|
||||
* Create a new EnumEditor, which can create an Enum by retrieving
|
||||
* the map of enum keys.
|
||||
*
|
||||
* <p>The fallbackToNull indicates whether null should be returned if
|
||||
* a null String is provided to the property editor or if the provided
|
||||
* String could not be used to locate an Enum. If set to true, null
|
||||
* will be returned. If set to false, IllegalArgumentException will be thrown.
|
||||
*/
|
||||
public <E extends Enum<E>>EnumEditor(Class<E> enumClass, boolean fallbackToNull) {
|
||||
this.enumClass = enumClass;
|
||||
this.fallbackToNull = fallbackToNull;
|
||||
}
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
public String getAsText() {
|
||||
String result = null;
|
||||
|
||||
if (getValue() != null) {
|
||||
result = ((Enum) getValue()).name();
|
||||
}
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Property Editor returning: " + result);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the Enum from the given text.
|
||||
*
|
||||
* @param text DOCUMENT ME!
|
||||
*
|
||||
* @throws IllegalArgumentException DOCUMENT ME!
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public void setAsText(String text) throws IllegalArgumentException {
|
||||
if (this.fallbackToNull && !StringUtils.hasText(text)) {
|
||||
// treat empty String as null value
|
||||
setValue(null);
|
||||
} else {
|
||||
Enum value = Enum.valueOf(this.enumClass, text);
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Property Editor converted '" + text + "' to object: " + value);
|
||||
}
|
||||
|
||||
setValue(value);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,51 +0,0 @@
|
|||
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* Licensed 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.acegisecurity.domain.util;
|
||||
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
|
||||
/**
|
||||
* Provides a helper that locates the declarated generics type of a class.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class GenericsUtils {
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
/**
|
||||
* Locates the first generic declaration on a class.
|
||||
*
|
||||
* @param clazz The class to introspect
|
||||
*
|
||||
* @return the first generic declaration, or <code>null</code> if cannot be determined
|
||||
*/
|
||||
public static Class getGeneric(Class clazz) {
|
||||
Type genType = clazz.getGenericSuperclass();
|
||||
|
||||
if (genType instanceof ParameterizedType) {
|
||||
Type[] params = ((ParameterizedType) genType).getActualTypeArguments();
|
||||
|
||||
if ((params != null) && (params.length == 1)) {
|
||||
return (Class) params[0];
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -1,116 +0,0 @@
|
|||
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* Licensed 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.acegisecurity.domain.util;
|
||||
|
||||
import org.acegisecurity.domain.PersistableEntity;
|
||||
|
||||
import org.apache.commons.lang.builder.ToStringStyle;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
import java.text.DateFormat;
|
||||
|
||||
import java.util.Calendar;
|
||||
import java.util.Collection;
|
||||
|
||||
|
||||
/**
|
||||
* Customized Commons Lang <code>ReflectionToStringBuilder</code> that ignores collections and inaccessible (ie
|
||||
* lazy-loaded) fields.
|
||||
*
|
||||
* @author Carlos Sanchez
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class ReflectionToStringBuilder extends org.apache.commons.lang.builder.ReflectionToStringBuilder {
|
||||
//~ Static fields/initializers =====================================================================================
|
||||
|
||||
private static DateFormat formatter = DateFormat.getDateTimeInstance();
|
||||
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
protected final transient Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
//~ Constructors ===================================================================================================
|
||||
|
||||
public ReflectionToStringBuilder(Object object) {
|
||||
super(object, ToStringStyle.MULTI_LINE_STYLE);
|
||||
}
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
protected boolean accept(Field field) {
|
||||
// Ignore if field inaccessible or collection
|
||||
try {
|
||||
Object o = getValue(field);
|
||||
|
||||
if (o != null) {
|
||||
if (o instanceof PersistableEntity) {
|
||||
Serializable id = ((PersistableEntity) o).getInternalId();
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(field + " id: " + id);
|
||||
}
|
||||
}
|
||||
|
||||
if (o instanceof Collection) {
|
||||
int size = ((Collection) o).size();
|
||||
this.append(field.getName(), "<collection with " + size + " elements>");
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(field + " size: " + size);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception fieldInaccessible) {
|
||||
this.append(field.getName(), "<inaccessible>");
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Inaccessible: " + field);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Accessible: " + field);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calendar fields are formatted with DateFormat.getDateTimeInstance() instead of using
|
||||
* Calendar.toString().
|
||||
*
|
||||
* @see org.apache.commons.lang.builder.ReflectionToStringBuilder#getValue(java.lang.reflect.Field)
|
||||
*/
|
||||
protected Object getValue(Field f) throws IllegalArgumentException, IllegalAccessException {
|
||||
Object value = super.getValue(f);
|
||||
|
||||
if (Calendar.class.isInstance(value)) {
|
||||
Calendar c = (Calendar) value;
|
||||
|
||||
return formatter.format(c.getTime());
|
||||
} else {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,6 +0,0 @@
|
|||
<html>
|
||||
<body>
|
||||
<p>Utilities useful in the domain package.</p>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,49 +0,0 @@
|
|||
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* Licensed 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.acegisecurity.domain.validation;
|
||||
|
||||
import org.springframework.validation.BindException;
|
||||
|
||||
|
||||
/**
|
||||
* Indicates a domain object wishes to perform additional binding before the
|
||||
* <code>Validator</code> is called.
|
||||
*
|
||||
* <p>
|
||||
* Typically this type of binding sets up private or protected properties that
|
||||
* the end user is not responsible for modifying. Whilst generally this can be
|
||||
* done by adding a hook to every property setter, the
|
||||
* <code>BindBeforeValidation</code> interface provides an AOP-style approach
|
||||
* that ensures missing hooks do not cause invalid object state.
|
||||
* </p>
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public interface BindBeforeValidation {
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
/**
|
||||
* This method will be called by infrastructure code before attempting to validate the object. Given this
|
||||
* method is called prior to validation, implementations of this method should <b>not</b> assume the object is in
|
||||
* a valid state.<p>Implementations should modify the object as required so that the <code>Validator</code>
|
||||
* will succeed if user-controllable properties are correct.</p>
|
||||
*
|
||||
* @throws BindException if there are problems that the method wish to advise (note that the <code>Validator</code>
|
||||
* should be allowed to determine errors in most cases, rather than this method doing so)
|
||||
*/
|
||||
public void bindSupport() throws BindException;
|
||||
}
|
|
@ -1,49 +0,0 @@
|
|||
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* Licensed 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.acegisecurity.domain.validation;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import org.springframework.validation.BindException;
|
||||
|
||||
|
||||
/**
|
||||
* Convenience class that invokes the {@link BindBeforeValidation} interface if the passed domain object has
|
||||
* requested it.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class BindBeforeValidationUtils {
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
/**
|
||||
* Call {@link BindBeforeValidation#bindSupport()} if the domain object requests it.
|
||||
*
|
||||
* @param domainObject to attempt to bind (never <code>null</code>)
|
||||
*
|
||||
* @throws BindException if the binding failed
|
||||
*/
|
||||
public static void bindIfRequired(Object domainObject)
|
||||
throws BindException {
|
||||
Assert.notNull(domainObject);
|
||||
|
||||
if (BindBeforeValidation.class.isAssignableFrom(domainObject.getClass())) {
|
||||
BindBeforeValidation bbv = (BindBeforeValidation) domainObject;
|
||||
bbv.bindSupport();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,48 +0,0 @@
|
|||
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* Licensed 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.acegisecurity.domain.validation;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
* Indicates a concrete class capable of introspecting a domain object for its
|
||||
* immediate children.
|
||||
*
|
||||
* <p>
|
||||
* Implementations may use a choice of reflective introspection or querying a
|
||||
* persistence metadata API to locate the internal children.
|
||||
* </p>
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public interface IntrospectionManager {
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
/**
|
||||
* Locates any direct children of a domain object.<p>Typically used with a {@link ValidationManager} to
|
||||
* validate each of the located children.</p>
|
||||
* <P>Implementations should only add the <b>immediate layer of children</b>. Grandchildren,
|
||||
* great-grandchildren etc should not be added.</p>
|
||||
*
|
||||
* @param parentObject the immediate parent which all children should share (guaranteed to never be
|
||||
* <code>null</code>)
|
||||
* @param allObjects the list to which this method should append each immediate child (guaranteed to never be
|
||||
* <code>null</code>)
|
||||
*/
|
||||
public void obtainImmediateChildren(Object parentObject, List<Object> allObjects);
|
||||
}
|
|
@ -1,105 +0,0 @@
|
|||
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* Licensed 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.acegisecurity.domain.validation;
|
||||
|
||||
import org.springframework.aop.framework.AopConfigException;
|
||||
import org.springframework.aop.support.StaticMethodMatcherPointcutAdvisor;
|
||||
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
|
||||
/**
|
||||
* Advisor for the {@link ValidationInterceptor}.<p>Intended to be used with Spring's
|
||||
* <code>DefaultAdvisorAutoProxyCreator</code>.</p>
|
||||
* <p>Registers {@link ValidationInterceptor} for every <code>Method</code> against a class that directly or
|
||||
* through its superclasses implements {@link #supportsClass} and has a signature match those defined by {@link
|
||||
* #methods}.</p>
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class ValidationAdvisor extends StaticMethodMatcherPointcutAdvisor implements InitializingBean {
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
private Class<?extends Object> supportsClass;
|
||||
private String[] methods = {"create", "update", "createOrUpdate"};
|
||||
|
||||
//~ Constructors ===================================================================================================
|
||||
|
||||
public ValidationAdvisor(ValidationInterceptor advice) {
|
||||
super(advice);
|
||||
|
||||
if (advice == null) {
|
||||
throw new AopConfigException("Cannot construct a BindAndValidateAdvisor using a "
|
||||
+ "null BindAndValidateInterceptor");
|
||||
}
|
||||
}
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
Assert.notNull(supportsClass, "A supportsClass is required");
|
||||
Assert.notNull(methods, "A list of valid methods is required");
|
||||
Assert.notEmpty(methods, "A list of valid methods is required");
|
||||
}
|
||||
|
||||
public String[] getMethods() {
|
||||
return methods;
|
||||
}
|
||||
|
||||
public Class getSupportsClass() {
|
||||
return supportsClass;
|
||||
}
|
||||
|
||||
public boolean matches(Method m, Class targetClass) {
|
||||
// Check there are actual arguments
|
||||
if (m.getParameterTypes().length == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check the method name matches one we're interested in
|
||||
boolean found = false;
|
||||
|
||||
for (int i = 0; i < methods.length; i++) {
|
||||
if (m.getName().equals(methods[i])) {
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check the target is of the type of class we wish to advise
|
||||
if (supportsClass.isAssignableFrom(targetClass)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public void setMethods(String[] methods) {
|
||||
this.methods = methods;
|
||||
}
|
||||
|
||||
public void setSupportsClass(Class<?extends Object> clazz) {
|
||||
this.supportsClass = clazz;
|
||||
}
|
||||
}
|
|
@ -1,99 +0,0 @@
|
|||
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* Licensed 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.acegisecurity.domain.validation;
|
||||
|
||||
import org.acegisecurity.domain.PersistableEntity;
|
||||
import org.acegisecurity.domain.impl.BusinessObject;
|
||||
|
||||
import org.aopalliance.intercept.MethodInterceptor;
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
|
||||
/**
|
||||
* Calls {@link ValidationManager} for method invocations.<p>For each method invocation, any argument that is
|
||||
* assignable from {@link #argumentClasses}<b>and</b> is non-<code>null</code> will be passed to the {@link
|
||||
* org.acegisecurity.domain.validation.ValidationManager} for processing.</p>
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class ValidationInterceptor implements MethodInterceptor, InitializingBean {
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
protected final Log logger = LogFactory.getLog(getClass());
|
||||
private ValidationManager validationManager;
|
||||
private Class<?>[] argumentClasses = {BusinessObject.class, PersistableEntity.class};
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
Assert.notNull(validationManager, "A ValidationManager is required");
|
||||
Assert.notEmpty(argumentClasses, "A list of business object classes to validate is required");
|
||||
}
|
||||
|
||||
public Class[] getArgumentClasses() {
|
||||
return argumentClasses;
|
||||
}
|
||||
|
||||
public ValidationManager getValidationManager() {
|
||||
return validationManager;
|
||||
}
|
||||
|
||||
public Object invoke(MethodInvocation mi) throws Throwable {
|
||||
Object[] args = mi.getArguments();
|
||||
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
if (shouldValidate(args[i])) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("ValidationInterceptor calling for: '" + args[i] + "'");
|
||||
}
|
||||
|
||||
validationManager.validate(args[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return mi.proceed();
|
||||
}
|
||||
|
||||
public void setArgumentClasses(Class[] argumentClasses) {
|
||||
this.argumentClasses = argumentClasses;
|
||||
}
|
||||
|
||||
public void setValidationManager(ValidationManager validationManager) {
|
||||
this.validationManager = validationManager;
|
||||
}
|
||||
|
||||
private boolean shouldValidate(Object argument) {
|
||||
if (argument == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < argumentClasses.length; i++) {
|
||||
if (argumentClasses[i].isAssignableFrom(argument.getClass())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -1,42 +0,0 @@
|
|||
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* Licensed 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.acegisecurity.domain.validation;
|
||||
|
||||
import org.springframework.validation.BindException;
|
||||
|
||||
|
||||
/**
|
||||
* Able to validate any passed domain object instance, including its children.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public interface ValidationManager {
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
/**
|
||||
* Validates the passed domain object, along with any children, grandchildren, great-grandchildren etc.<p>Before
|
||||
* performing validation, implementations must execute {@link BindBeforeValidation} for any domain objects
|
||||
* requesting it.</p>
|
||||
*
|
||||
* @param domainObject to validate (cannot be <code>null</code>)
|
||||
*
|
||||
* @throws BindException if a validation problem occurs
|
||||
* @throws ValidatorNotFoundException if no matching <code>Validator</code> could be found (and the implementation
|
||||
* wishes to treat this as an exception condition as opposed to logging it and continuing).
|
||||
*/
|
||||
public void validate(Object domainObject) throws BindException, ValidatorNotFoundException;
|
||||
}
|
|
@ -1,221 +0,0 @@
|
|||
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* Licensed 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.acegisecurity.domain.validation;
|
||||
|
||||
import org.acegisecurity.domain.dao.DetachmentContextHolder;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import org.springframework.validation.BindException;
|
||||
import org.springframework.validation.Errors;
|
||||
import org.springframework.validation.Validator;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Vector;
|
||||
|
||||
|
||||
/**
|
||||
* Default implementation of {@link ValidationManager}.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @author Matthew E. Porter
|
||||
* @version $Id$
|
||||
*/
|
||||
public class ValidationManagerImpl implements InitializingBean, ValidationManager {
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
private IntrospectionManager introspectionManager;
|
||||
protected final Log logger = LogFactory.getLog(getClass());
|
||||
private ValidationRegistryManager validationRegistryManager = new ValidationRegistryManagerImpl();
|
||||
private boolean strictValidation = true;
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
Assert.notNull(validationRegistryManager, "A ValidationRegistryManager is required");
|
||||
Assert.notNull(introspectionManager, "An IntrospectionManager is required");
|
||||
}
|
||||
|
||||
private Validator findValidator(Class clazz) throws ValidatorNotFoundException {
|
||||
Assert.notNull(clazz, "Class cannot be null");
|
||||
|
||||
Validator validator = this.validationRegistryManager.findValidator(clazz);
|
||||
|
||||
if (validator == null) {
|
||||
throw new ValidatorNotFoundException("No Validator found for class '" + clazz + "'");
|
||||
}
|
||||
|
||||
return validator;
|
||||
}
|
||||
|
||||
public IntrospectionManager getIntrospectionManager() {
|
||||
return introspectionManager;
|
||||
}
|
||||
|
||||
public ValidationRegistryManager getValidationRegistryManager() {
|
||||
return validationRegistryManager;
|
||||
}
|
||||
|
||||
public boolean isStrictValidation() {
|
||||
return strictValidation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Locates all immediate children of the passed <code>parentObject</code>, adding each of those immediate
|
||||
* children to the <code>allObjects</code> list and then calling this same method for each of those immediate
|
||||
* children.<p>Does <b>not</b> add the passed <code>parentObject</code> to the <code>allObjects</code>
|
||||
* list. The caller of this method should ensure the <code>parentObject</code> is added to the list instead.</p>
|
||||
*
|
||||
* @param parentObject the object we wish to locate all children for
|
||||
* @param allObjects the list to add the located children to
|
||||
*/
|
||||
private void obtainAllChildren(Object parentObject, List<Object> allObjects) {
|
||||
Assert.notNull(parentObject, "Violation of parentObject method contract");
|
||||
Assert.notNull(allObjects, "Violation of allObjects method contract");
|
||||
Assert.isTrue(allObjects.contains(parentObject), "List of objects missing the requested parentObject");
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Searching for children of " + parentObject);
|
||||
}
|
||||
|
||||
// Add immediate children of this domain object
|
||||
List<Object> currentChildren = new Vector<Object>();
|
||||
introspectionManager.obtainImmediateChildren(parentObject, currentChildren);
|
||||
|
||||
// Now iterate the children, adding their children to the object list
|
||||
Iterator<Object> childrenIter = currentChildren.iterator();
|
||||
|
||||
while (childrenIter.hasNext()) {
|
||||
Object childObject = childrenIter.next();
|
||||
|
||||
if (childObject != null) {
|
||||
if (allObjects.contains(childObject)) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Already processed this object (will not re-add): " + childObject);
|
||||
}
|
||||
} else {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(
|
||||
"New child object found; adding child object to list of objects, and searching for its children: "
|
||||
+ childObject);
|
||||
}
|
||||
|
||||
allObjects.add(childObject);
|
||||
obtainAllChildren(childObject, allObjects);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setIntrospectionManager(IntrospectionManager introspectionManager) {
|
||||
this.introspectionManager = introspectionManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether a {@link ValidatorNotFoundException} should be thrown if any domain object does not
|
||||
* have a corresponding <code>Validator</code>.<p>Defaults to <code>true</code>. This is a reasonable
|
||||
* default, as callers of <code>ValidationManager</code> should expect the object to support validation.</p>
|
||||
*
|
||||
* @param strictValidation set to <code>false</code> if you wish to silently ignore any domain object that is
|
||||
* missing a <code>Validator</code>
|
||||
*/
|
||||
public void setStrictValidation(boolean strictValidation) {
|
||||
this.strictValidation = strictValidation;
|
||||
}
|
||||
|
||||
public void setValidationRegistryManager(ValidationRegistryManager validationRegistryManager) {
|
||||
this.validationRegistryManager = validationRegistryManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the passed domain object, along with any children, grandchildren, great-grandchildren etc.
|
||||
*
|
||||
* @param domainObject to validate (cannot be <code>null</code>)
|
||||
*
|
||||
* @throws BindException if a validation problem occurs
|
||||
* @throws ValidatorNotFoundException if no matching <code>Validator</code> could be found for the object or its
|
||||
* children (only ever thrown if the {@link #strictValidation}) was set to <code>true</code>).
|
||||
*/
|
||||
public void validate(Object domainObject) throws BindException, ValidatorNotFoundException {
|
||||
// Abort if null
|
||||
Assert.notNull(domainObject, "Cannot validate a null domain object, as unable to getClass()");
|
||||
|
||||
// Construct a list of objects to be validated and adds self
|
||||
List<Object> allObjects = new Vector<Object>();
|
||||
allObjects.add(domainObject);
|
||||
|
||||
// Add all children (and grandchildren, great-grandchildren etc)
|
||||
// of domain object to the list of objects to be validated
|
||||
// (list never contains null)
|
||||
obtainAllChildren(domainObject, allObjects);
|
||||
|
||||
Assert.notEmpty(allObjects, "The list of objects to be validated was empty");
|
||||
|
||||
// Process list of objects to be validated by validating each
|
||||
Iterator<Object> iter = allObjects.iterator();
|
||||
|
||||
while (iter.hasNext()) {
|
||||
Object currentDomainObject = iter.next();
|
||||
Class clazz = currentDomainObject.getClass();
|
||||
|
||||
DetachmentContextHolder.setForceReturnOfDetachedInstances(true);
|
||||
|
||||
try {
|
||||
// Call bindSupport() if this class wishes
|
||||
BindBeforeValidationUtils.bindIfRequired(currentDomainObject);
|
||||
|
||||
Errors errors = new BindException(currentDomainObject, clazz.getName());
|
||||
Validator v = findValidator(clazz);
|
||||
|
||||
// Perform validation
|
||||
v.validate(currentDomainObject, errors);
|
||||
|
||||
// Handle validation outcome
|
||||
if (errors.getErrorCount() == 0) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Validated '" + clazz + "' successfully using '" + v.getClass() + "'");
|
||||
}
|
||||
} else {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Validated '" + clazz + "' using '" + v.getClass() + "' but errors detected");
|
||||
}
|
||||
|
||||
throw (BindException) errors;
|
||||
}
|
||||
} catch (ValidatorNotFoundException validatorNotFoundException) {
|
||||
if (strictValidation) {
|
||||
if (logger.isErrorEnabled()) {
|
||||
logger.error(validatorNotFoundException);
|
||||
}
|
||||
|
||||
throw validatorNotFoundException;
|
||||
}
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Could not locate validator for class '" + clazz + "'; skipping without error");
|
||||
}
|
||||
} finally {
|
||||
DetachmentContextHolder.setForceReturnOfDetachedInstances(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,48 +0,0 @@
|
|||
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* Licensed 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.acegisecurity.domain.validation;
|
||||
|
||||
import org.springframework.validation.Validator;
|
||||
|
||||
|
||||
/**
|
||||
* <code>ValidationRegistryManager</code> implementations are able to
|
||||
* authoritatively return a <code>Validator</code> instance that is suitable
|
||||
* for a given domain object.
|
||||
*
|
||||
* <p>
|
||||
* Implementations are free to implement their own strategy for maintaining the
|
||||
* list of <code>Validator</code>s, or create them on-demand if preferred.
|
||||
* This interface is non-prescriptive.
|
||||
* </p>
|
||||
*
|
||||
* @author Matthew E. Porter
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public interface ValidationRegistryManager {
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
/**
|
||||
* Obtains the <code>Validator</code> that applies for a given domain object class.
|
||||
*
|
||||
* @param domainClass that a <code>Validator</code> is required for
|
||||
*
|
||||
* @return the <code>Validator</code>, or <code>null</code> if no <code>Validator</code> is known for the indicated
|
||||
* <code>domainClass</code>
|
||||
*/
|
||||
public Validator findValidator(Class domainClass);
|
||||
}
|
|
@ -1,154 +0,0 @@
|
|||
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* Licensed 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.acegisecurity.domain.validation;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.beans.factory.BeanFactoryUtils;
|
||||
import org.springframework.beans.factory.ListableBeanFactory;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import org.springframework.validation.Validator;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
|
||||
/**
|
||||
* A basic implementation of {@link ValidationRegistryManager}.<p>Locates <code>Validator</code>s registered in
|
||||
* bean factory.</p>
|
||||
* <p>If more than one <code>Validator</code> can support a given object, the supporting <code>Validator</code>s
|
||||
* will be iterated and their bean factory defined bean names will be used to attempt to select the "best matching"
|
||||
* <code>Validator</code>. The lowercase version of a given object's simplified class name will be searched within the
|
||||
* bean names. If more than one <code>Validator</code> contains this search criteria, an exception will be thrown as
|
||||
* the actual intended <code>Validator</code> is unidentifiable.</p>
|
||||
* <p>For example, say you had a PartyValidator which could validate com.foo.Party, and also its subclass,
|
||||
* com.foo.Person. There is also a PersonValidator which can only validate Person. PartyValidator and PersonValidator
|
||||
* are registered in the bean container as "partyValidator" and "personValidator". When
|
||||
* <code>ValidationRegistryManagerImpl</code> is asked to return the <code>Validator</code> for Person, it will locate
|
||||
* the two matching <code>Validator</code>s in the bean container. As there are two matching, it will look at the
|
||||
* lowercase representation of the bean names and see if either contain the lower simplified class name of the object
|
||||
* being search for (com.foo.Person thus becomes simply "person"). <code>ValidationRegistryManagerImpl</code> will
|
||||
* then correctly return the PersonValidator for Person. If the PartyValidator had been registered with an ambiguous
|
||||
* bean name of say "personAndPartyValidator", both bean names would have matched and an exception would have been
|
||||
* thrown.</p>
|
||||
*
|
||||
* @author Matthew E. Porter
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class ValidationRegistryManagerImpl implements ValidationRegistryManager, BeanFactoryAware {
|
||||
//~ Instance fields ================================================================================================
|
||||
|
||||
private ListableBeanFactory bf;
|
||||
private Map<Class, String> validatorMap = new HashMap<Class, String>();
|
||||
|
||||
//~ Methods ========================================================================================================
|
||||
|
||||
public Validator findValidator(Class domainClass) {
|
||||
Assert.notNull(domainClass, "domainClass cannot be null");
|
||||
|
||||
if (validatorMap.containsKey(domainClass)) {
|
||||
if (validatorMap.get(domainClass) == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (Validator) this.bf.getBean((String) validatorMap.get(domainClass), Validator.class);
|
||||
}
|
||||
|
||||
// Attempt to find Validator via introspection
|
||||
Map<String, Validator> beans = BeanFactoryUtils.beansOfTypeIncludingAncestors(bf, Validator.class, true, true);
|
||||
|
||||
// Search all Validators for those that support the class
|
||||
Set<String> candidateValidatorNames = new HashSet<String>();
|
||||
Iterator<String> iter = beans.keySet().iterator();
|
||||
|
||||
while (iter.hasNext()) {
|
||||
String beanName = iter.next();
|
||||
Validator validator = beans.get(beanName);
|
||||
|
||||
if (validator.supports(domainClass)) {
|
||||
candidateValidatorNames.add(beanName);
|
||||
}
|
||||
}
|
||||
|
||||
if (candidateValidatorNames.size() == 0) {
|
||||
// No Validator found
|
||||
this.validatorMap.put(domainClass, null);
|
||||
|
||||
return null;
|
||||
} else if (candidateValidatorNames.size() == 1) {
|
||||
// Only one Validator found, so return it
|
||||
String validator = candidateValidatorNames.iterator().next();
|
||||
this.validatorMap.put(domainClass, validator);
|
||||
|
||||
return beans.get(validator);
|
||||
} else {
|
||||
// Try to locate an entry with simple class name in it
|
||||
StringBuffer sb = new StringBuffer();
|
||||
Iterator<String> iterCandidates = candidateValidatorNames.iterator();
|
||||
String lastFound = null;
|
||||
int numberFound = 0;
|
||||
|
||||
while (iterCandidates.hasNext()) {
|
||||
String candidate = iterCandidates.next();
|
||||
sb.append(candidate);
|
||||
|
||||
if (iterCandidates.hasNext()) {
|
||||
sb.append(",");
|
||||
}
|
||||
|
||||
if (candidate.toLowerCase().contains(domainClass.getSimpleName().toLowerCase())) {
|
||||
numberFound++;
|
||||
lastFound = candidate;
|
||||
}
|
||||
}
|
||||
|
||||
if (numberFound != 1) {
|
||||
throw new IllegalArgumentException("More than one Validator found (" + sb.toString()
|
||||
+ ") that supports '" + domainClass
|
||||
+ "', but cannot determine the most specific Validator to use; give a hint by making bean name include the simple name of the target class ('"
|
||||
+ domainClass.getSimpleName().toString() + "')");
|
||||
}
|
||||
|
||||
this.validatorMap.put(domainClass, lastFound);
|
||||
|
||||
return beans.get(lastFound);
|
||||
}
|
||||
}
|
||||
|
||||
public void registerValidator(Class domainClass, String beanName) {
|
||||
Assert.notNull(domainClass, "domainClass cannot be null");
|
||||
Assert.notNull(beanName, "beanName cannot be null");
|
||||
Assert.isTrue(this.bf.containsBean(beanName), "beanName not found in context");
|
||||
Assert.isInstanceOf(Validator.class, this.bf.getBean(beanName),
|
||||
"beanName '" + beanName + "' must be a Validator");
|
||||
Assert.isTrue(((Validator) this.bf.getBean(beanName)).supports(domainClass),
|
||||
"Validator does not support " + domainClass);
|
||||
this.validatorMap.put(domainClass, beanName);
|
||||
}
|
||||
|
||||
public void setBeanFactory(BeanFactory beanFactory)
|
||||
throws BeansException {
|
||||
Assert.isInstanceOf(ListableBeanFactory.class, beanFactory, "BeanFactory must be ListableBeanFactory");
|
||||
this.bf = (ListableBeanFactory) beanFactory;
|
||||
}
|
||||
}
|
|
@ -1,50 +0,0 @@
|
|||
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* Licensed 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.acegisecurity.domain.validation;
|
||||
|
||||
import org.acegisecurity.domain.DomainException;
|
||||
|
||||
|
||||
/**
|
||||
* Thrown if no <code>Validator</code> could be found that supports a domain object presented for validation.
|
||||
*
|
||||
* @author Ben Alex
|
||||
* @version $Id$
|
||||
*/
|
||||
public class ValidatorNotFoundException extends DomainException {
|
||||
//~ Constructors ===================================================================================================
|
||||
|
||||
/**
|
||||
* Constructs a <code>ValidatorNotFoundException</code> with the specified
|
||||
* message and root cause.
|
||||
*
|
||||
* @param msg the detail message
|
||||
* @param t the root cause
|
||||
*/
|
||||
public ValidatorNotFoundException(String msg, Throwable t) {
|
||||
super(msg, t);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a <code>DomainException</code> with the specified message and
|
||||
* no root cause.
|
||||
*
|
||||
* @param msg the detail message
|
||||
*/
|
||||
public ValidatorNotFoundException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
}
|
|
@ -1,42 +0,0 @@
|
|||
<html>
|
||||
<body>
|
||||
<p>Validation services for complex domain objects.</p>
|
||||
|
||||
<p>Generally you will write <code>Validator</code>s for each of your domain
|
||||
objects, and add a {@link ValidationManager} to your application context. You
|
||||
will need to wire a suitable {@link IntrospectionManager} against the
|
||||
<code>ValidationManager</code> so that children of a domain object presented
|
||||
for validation can be identified and in turn also validated.
|
||||
|
||||
<p>The {@link ValidationInterceptor} and {@link ValidationAdvisor} are provided,
|
||||
although their use is not recommended against DAOs given many <code>Validator</code>s
|
||||
require a DAO and this will cause a loop that results in the DAO not being
|
||||
advised. Instead your DAO implementations should have their mutator methods
|
||||
pass the object to the <code>ValidationManager</code> prior to persistence. This
|
||||
is a non-AOP approach, but represetns a practical solution.</p>
|
||||
|
||||
<p>If you domain objects themselves wish to ensure they are in a valid state
|
||||
prior to internal business methods being invoked, it is suggested they provide
|
||||
a <code>ValidationManager</code> collaborator, and fire its validate method.
|
||||
Such collaborator can be autowired during both instance retrieval and creation.
|
||||
It should generally also be marked as <code>transient</code>, to avoid possible
|
||||
serialisation issues if used inside a <code>HttpSession</code> or similar.</p>
|
||||
|
||||
<p>Sometimes domain objects need to internally update themselves before being
|
||||
validated. Any such domain objects should implement {@link BindBeforeValidation}.
|
||||
The <code>ValidationManager</code> will fire the related method just prior to
|
||||
validation, and you can do it manually using {@link BindBeforeValidationUtils}.
|
||||
Using the utility class is generally preferred over calling the method
|
||||
directly, as it ignores classes that do not implement
|
||||
<code>BindBeforeValidation</code>.</p>
|
||||
|
||||
<p>Finally, sometimes <code>Validator</code>s might need to perform queries
|
||||
against a persistence or services layer. For example, the <code>Validator</code>
|
||||
may be checking no other user has this username, or comparing the object's old
|
||||
state to detect modifications that violate business rules. If using an ORM tool
|
||||
such as Hibernate, it is recommended you use the <code>EvictionUtils</code>
|
||||
static methods to remove objects from the session.
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1 +0,0 @@
|
|||
*.log
|
|
@ -1,6 +0,0 @@
|
|||
<html>
|
||||
<body>
|
||||
<p>Domain's resources.</p>
|
||||
</body>
|
||||
</html>
|
||||
|
1
pom.xml
1
pom.xml
|
@ -10,7 +10,6 @@
|
|||
<module>core</module>
|
||||
<module>core-tiger</module>
|
||||
<module>adapters</module>
|
||||
<module>domain</module>
|
||||
</modules>
|
||||
|
||||
<description>Acegi Security System for Spring</description>
|
||||
|
|
|
@ -63,7 +63,7 @@ maven.license.licenseFile=${rootdir}/LICENSE.txt
|
|||
|
||||
# multiproject
|
||||
maven.multiproject.basedir=${rootdir}
|
||||
maven.multiproject.includes=core/project.xml,adapters/*/project.xml,samples/*/project.xml,domain/project.xml,core-tiger/project.xml
|
||||
maven.multiproject.includes=core/project.xml,adapters/*/project.xml,samples/*/project.xml,core-tiger/project.xml
|
||||
|
||||
# excluding the attributes project since the Commons Attributes plugin causes
|
||||
# problems with java 5 source code compilation
|
||||
|
|
Loading…
Reference in New Issue