51 changed files with 1 additions and 3843 deletions
@ -1,5 +0,0 @@
@@ -1,5 +0,0 @@
|
||||
target |
||||
.settings |
||||
.classpath |
||||
.project |
||||
.wtpmodules |
||||
@ -1,42 +0,0 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -1,6 +0,0 @@
|
||||
<html> |
||||
<body> |
||||
<p>Hibernate-specific implementations of the domain subproject interfaces.</p> |
||||
</body> |
||||
</html> |
||||
|
||||
@ -1,57 +0,0 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -1,6 +0,0 @@
|
||||
<html> |
||||
<body> |
||||
<p>Provides tools to assist develop rich domain object models.</p> |
||||
</body> |
||||
</html> |
||||
|
||||
@ -1,151 +0,0 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -1,6 +0,0 @@
|
||||
<html> |
||||
<body> |
||||
<p>Utilities useful in the domain package.</p> |
||||
</body> |
||||
</html> |
||||
|
||||
@ -1,49 +0,0 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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,6 +0,0 @@
@@ -1,6 +0,0 @@
|
||||
<html> |
||||
<body> |
||||
<p>Domain's resources.</p> |
||||
</body> |
||||
</html> |
||||
|
||||
Loading…
Reference in new issue