Initial commit.
This commit is contained in:
parent
046dd2611c
commit
cf241fb9ae
|
@ -1,6 +1,10 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<classpath>
|
<classpath>
|
||||||
<classpathentry kind="src" path="samples/attributes/src/main/java"/>
|
<classpathentry kind="src" path="samples/attributes/src/main/java"/>
|
||||||
|
<classpathentry kind="src" path="domain/src/main/java"/>
|
||||||
|
<classpathentry kind="src" path="domain/src/main/resource"/>
|
||||||
|
<classpathentry kind="src" path="domain/src/test/java"/>
|
||||||
|
<classpathentry kind="src" path="domain/src/test/resources"/>
|
||||||
<classpathentry kind="src" path="adapters/catalina/src/main/resources"/>
|
<classpathentry kind="src" path="adapters/catalina/src/main/resources"/>
|
||||||
<classpathentry kind="src" path="samples/attributes/src/main/resources"/>
|
<classpathentry kind="src" path="samples/attributes/src/main/resources"/>
|
||||||
<classpathentry kind="src" path="samples/attributes/src/test/java"/>
|
<classpathentry kind="src" path="samples/attributes/src/test/java"/>
|
||||||
|
@ -53,5 +57,8 @@
|
||||||
<classpathentry kind="var" path="MAVEN_REPO/junit/jars/junit-3.8.1.jar"/>
|
<classpathentry kind="var" path="MAVEN_REPO/junit/jars/junit-3.8.1.jar"/>
|
||||||
<classpathentry kind="var" path="MAVEN_REPO/ehcache/jars/ehcache-1.1.jar"/>
|
<classpathentry kind="var" path="MAVEN_REPO/ehcache/jars/ehcache-1.1.jar"/>
|
||||||
<classpathentry kind="var" path="MAVEN_REPO/jspapi/jars/jsp-api-2.0.jar"/>
|
<classpathentry kind="var" path="MAVEN_REPO/jspapi/jars/jsp-api-2.0.jar"/>
|
||||||
|
<classpathentry kind="var" path="MAVEN_REPO/hibernate/jars/hibernate-2.1.8.jar"/>
|
||||||
|
<classpathentry kind="var" path="MAVEN_REPO/commons-lang/jars/commons-lang-2.0.jar"/>
|
||||||
|
<classpathentry sourcepath="DIST_BASE/commons-beanutils-1.6.1-src/src/java" kind="var" path="MAVEN_REPO/commons-beanutils/jars/commons-beanutils-1.6.1.jar"/>
|
||||||
<classpathentry kind="output" path="target/eclipseclasses"/>
|
<classpathentry kind="output" path="target/eclipseclasses"/>
|
||||||
</classpath>
|
</classpath>
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
<!--
|
||||||
|
* ========================================================================
|
||||||
|
*
|
||||||
|
* 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"
|
||||||
|
>
|
||||||
|
|
||||||
|
<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>
|
|
@ -0,0 +1,53 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project>
|
||||||
|
<extend>${basedir}/../project.xml</extend>
|
||||||
|
<pomVersion>3</pomVersion>
|
||||||
|
<artifactId>acegi-security-domain</artifactId>
|
||||||
|
<name>Acegi Security System for Spring - Domain Object Support</name>
|
||||||
|
<groupId>acegisecurity</groupId>
|
||||||
|
<siteDirectory>/home/groups/a/ac/acegisecurity/htdocs/multiproject/acegi-security-domain</siteDirectory>
|
||||||
|
<repository>
|
||||||
|
<connection>scm:cvs:pserver:anonymous@cvs.sourceforge.net:/cvsroot/acegisecurity:acegisecurity</connection>
|
||||||
|
<developerConnection>scm:cvs:ext:${maven.username}@cvs.sourceforge.net:/cvsroot/acegisecurity:acegisecurity</developerConnection>
|
||||||
|
<url>http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/acegisecurity/acegisecurity/domain/</url>
|
||||||
|
</repository>
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>hibernate</groupId>
|
||||||
|
<artifactId>hibernate</artifactId>
|
||||||
|
<version>2.1.8</version>
|
||||||
|
<type>jar</type>
|
||||||
|
</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>acegisecurity</groupId>
|
||||||
|
<artifactId>acegi-security</artifactId>
|
||||||
|
<version>0.8.2-SNAPSHOT</version>
|
||||||
|
<type>jar</type>
|
||||||
|
</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>
|
||||||
|
|
|
@ -0,0 +1,51 @@
|
||||||
|
/* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package net.sf.acegisecurity.domain;
|
||||||
|
|
||||||
|
import net.sf.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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,56 @@
|
||||||
|
/* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package net.sf.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 net.sf.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
|
||||||
|
*/
|
||||||
|
abstract Serializable getInternalId();
|
||||||
|
}
|
|
@ -0,0 +1,172 @@
|
||||||
|
/* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package net.sf.acegisecurity.domain.dao;
|
||||||
|
|
||||||
|
import net.sf.acegisecurity.domain.PersistableEntity;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides fundamental DAO capabilities for a single concrete {@link
|
||||||
|
* PersistableEntity}.
|
||||||
|
*
|
||||||
|
* <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, casting to and from concrete {@link
|
||||||
|
* net.sf.acegisecurity.domain.PersistableEntity}s, 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 {
|
||||||
|
//~ Methods ================================================================
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new object, with the current {@link
|
||||||
|
* PersistableEntity#getInternalId()} value being ignored.
|
||||||
|
*
|
||||||
|
* @param value (without the identity property initialized)
|
||||||
|
*
|
||||||
|
* @return the value created (with the identity property initialised)
|
||||||
|
*/
|
||||||
|
public PersistableEntity create(PersistableEntity value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Saves an existing object to the persistence layer, or creates a new
|
||||||
|
* object in the persistence layer. Implementations typically rely on
|
||||||
|
* {@link PersistableEntity#getInternalId()} being non-<code>null</code>
|
||||||
|
* to differentiate between persistence instances previous saved and those
|
||||||
|
* requiring initial creation.
|
||||||
|
*
|
||||||
|
* @param value to save or update
|
||||||
|
*
|
||||||
|
* @return the saved or updated (as appropriate) value
|
||||||
|
*/
|
||||||
|
public PersistableEntity createOrUpdate(PersistableEntity value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete an object.
|
||||||
|
*
|
||||||
|
* @param value the value to delete
|
||||||
|
*/
|
||||||
|
public void delete(PersistableEntity value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return all persistent instances.
|
||||||
|
*
|
||||||
|
* @return all persistence instances (an empty <code>List</code> will be
|
||||||
|
* returned if no matches are found)
|
||||||
|
*/
|
||||||
|
public List findAll();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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)
|
||||||
|
*/
|
||||||
|
public List findId(Collection ids);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load a persistent instance by its identifier.
|
||||||
|
*
|
||||||
|
* @param id the identifier of the persistent instance desired to be
|
||||||
|
* retrieved
|
||||||
|
*
|
||||||
|
* @return the request item, or <code>null</code> if not found
|
||||||
|
*/
|
||||||
|
public PersistableEntity readId(Serializable id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
||||||
|
* @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)
|
||||||
|
*/
|
||||||
|
public PaginatedList scroll(PersistableEntity value, int firstElement,
|
||||||
|
int maxElements, String orderByAsc);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
||||||
|
*
|
||||||
|
* @return the updated value
|
||||||
|
*/
|
||||||
|
public PersistableEntity update(PersistableEntity value);
|
||||||
|
}
|
|
@ -0,0 +1,52 @@
|
||||||
|
/* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package net.sf.acegisecurity.domain.dao;
|
||||||
|
|
||||||
|
import net.sf.acegisecurity.domain.PersistableEntity;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates an implementation capable of evicting {@link
|
||||||
|
* net.sf.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);
|
||||||
|
}
|
|
@ -0,0 +1,105 @@
|
||||||
|
/* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package net.sf.acegisecurity.domain.dao;
|
||||||
|
|
||||||
|
import net.sf.acegisecurity.domain.PersistableEntity;
|
||||||
|
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
|
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 (never <code>null</code>)
|
||||||
|
*/
|
||||||
|
public static void evictIfRequired(Object daoOrServices,
|
||||||
|
PersistableEntity entity) {
|
||||||
|
Assert.notNull(entity, "Cannot evict an empty PersistableEntity object!");
|
||||||
|
|
||||||
|
EvictionCapable evictor = getEvictionCapable(daoOrServices);
|
||||||
|
|
||||||
|
if (evictor != 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 collection) {
|
||||||
|
Assert.notNull(collection, "Cannot evict a null Collection");
|
||||||
|
|
||||||
|
if (getEvictionCapable(daoOrServices) == null) {
|
||||||
|
// save expense of iterating collection
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Iterator iter = collection.iterator();
|
||||||
|
|
||||||
|
while (iter.hasNext()) {
|
||||||
|
Object obj = iter.next();
|
||||||
|
|
||||||
|
if (obj instanceof PersistableEntity) {
|
||||||
|
evictIfRequired(daoOrServices, (PersistableEntity) obj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,477 @@
|
||||||
|
/* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package net.sf.acegisecurity.domain.dao;
|
||||||
|
|
||||||
|
import net.sf.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.Vector;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* Represents a 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$
|
||||||
|
*/
|
||||||
|
public class PaginatedList implements List {
|
||||||
|
//~ Instance fields ========================================================
|
||||||
|
|
||||||
|
protected final transient Log logger = LogFactory.getLog(getClass());
|
||||||
|
private List list;
|
||||||
|
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(PersistableEntity entity) {
|
||||||
|
if (entity == null) {
|
||||||
|
this.list = new Vector();
|
||||||
|
this.firstElement = 0;
|
||||||
|
this.maxElements = Integer.MAX_VALUE;
|
||||||
|
this.size = 0;
|
||||||
|
} else {
|
||||||
|
List list = new Vector();
|
||||||
|
list.add(entity);
|
||||||
|
this.list = list;
|
||||||
|
this.firstElement = 0;
|
||||||
|
this.maxElements = Integer.MAX_VALUE;
|
||||||
|
this.size = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public PaginatedList(List list, int firstElement, int maxElements, int size) {
|
||||||
|
this.list = list;
|
||||||
|
this.firstElement = firstElement;
|
||||||
|
this.maxElements = maxElements;
|
||||||
|
this.size = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
//~ Methods ================================================================
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unsupported operation
|
||||||
|
*
|
||||||
|
* @return DOCUMENT ME!
|
||||||
|
*
|
||||||
|
* @throws UnsupportedOperationException
|
||||||
|
*
|
||||||
|
* @see java.util.Collection#isEmpty()
|
||||||
|
*/
|
||||||
|
public boolean isEmpty() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFirstElement(int firstElement) {
|
||||||
|
this.firstElement = firstElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setList(List list) {
|
||||||
|
this.list = list;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get list with the elements of this page.
|
||||||
|
*
|
||||||
|
* @return this page of the results
|
||||||
|
*/
|
||||||
|
public List getList() {
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMaxElements(int maxElements) {
|
||||||
|
this.maxElements = maxElements;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the number of elements in all the pages
|
||||||
|
*
|
||||||
|
* @param size DOCUMENT ME!
|
||||||
|
*/
|
||||||
|
public void setSize(int size) {
|
||||||
|
this.size = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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, Object 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(Object 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 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 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 Object get(int arg0) {
|
||||||
|
return list.get(arg0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Iterator iterator() {
|
||||||
|
return new PaginatedListIterator(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 listIterator() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unsupported operation
|
||||||
|
*
|
||||||
|
* @param arg0 DOCUMENT ME!
|
||||||
|
*
|
||||||
|
* @return DOCUMENT ME!
|
||||||
|
*
|
||||||
|
* @throws UnsupportedOperationException
|
||||||
|
*
|
||||||
|
* @see java.util.List#listIterator(int)
|
||||||
|
*/
|
||||||
|
public ListIterator listIterator(int arg0) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unsupported operation
|
||||||
|
*
|
||||||
|
* @param arg0 DOCUMENT ME!
|
||||||
|
*
|
||||||
|
* @return DOCUMENT ME!
|
||||||
|
*
|
||||||
|
* @throws UnsupportedOperationException
|
||||||
|
*
|
||||||
|
* @see java.util.List#remove(int)
|
||||||
|
*/
|
||||||
|
public Object 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 Object set(int arg0, Object arg1) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 subList(int arg0, int arg1) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object[] toArray() {
|
||||||
|
return list.toArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object[] toArray(Object[] arg0) {
|
||||||
|
if (logger.isDebugEnabled()) {
|
||||||
|
logger.debug("List size when convert to array "
|
||||||
|
+ list.toArray().length);
|
||||||
|
}
|
||||||
|
|
||||||
|
return list.toArray(arg0);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,92 @@
|
||||||
|
/* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package net.sf.acegisecurity.domain.dao;
|
||||||
|
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.NoSuchElementException;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An iterator of the <code>PaginatedList</code>.
|
||||||
|
*
|
||||||
|
* @author Carlos Sanchez
|
||||||
|
* @version $Id$
|
||||||
|
*/
|
||||||
|
public class PaginatedListIterator implements Iterator {
|
||||||
|
//~ Instance fields ========================================================
|
||||||
|
|
||||||
|
private Iterator iterator;
|
||||||
|
private PaginatedList list;
|
||||||
|
private int i = 0;
|
||||||
|
|
||||||
|
//~ Constructors ===========================================================
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DOCUMENT ME!
|
||||||
|
*
|
||||||
|
* @param list
|
||||||
|
*/
|
||||||
|
public PaginatedListIterator(PaginatedList list) {
|
||||||
|
this.list = list;
|
||||||
|
}
|
||||||
|
|
||||||
|
//~ Methods ================================================================
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see java.util.Iterator#hasNext()
|
||||||
|
*/
|
||||||
|
public boolean hasNext() {
|
||||||
|
return i < list.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 Object next() {
|
||||||
|
if (i == list.getFirstElement()) {
|
||||||
|
iterator = list.getList().iterator();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((i >= list.getFirstElement())
|
||||||
|
&& (i < (list.getFirstElement() + list.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();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
<p>Provides the base of a data access object (DAO) persistence layer.</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
|
@ -0,0 +1,269 @@
|
||||||
|
/* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package net.sf.acegisecurity.domain.hibernate;
|
||||||
|
|
||||||
|
import net.sf.acegisecurity.domain.PersistableEntity;
|
||||||
|
import net.sf.acegisecurity.domain.dao.Dao;
|
||||||
|
import net.sf.acegisecurity.domain.dao.EvictionCapable;
|
||||||
|
import net.sf.acegisecurity.domain.dao.PaginatedList;
|
||||||
|
|
||||||
|
import net.sf.hibernate.Criteria;
|
||||||
|
import net.sf.hibernate.Hibernate;
|
||||||
|
import net.sf.hibernate.HibernateException;
|
||||||
|
import net.sf.hibernate.Session;
|
||||||
|
import net.sf.hibernate.expression.Expression;
|
||||||
|
import net.sf.hibernate.expression.MatchMode;
|
||||||
|
import net.sf.hibernate.expression.Order;
|
||||||
|
import net.sf.hibernate.metadata.ClassMetadata;
|
||||||
|
import net.sf.hibernate.type.Type;
|
||||||
|
|
||||||
|
import org.springframework.orm.hibernate.HibernateCallback;
|
||||||
|
import org.springframework.orm.hibernate.HibernateObjectRetrievalFailureException;
|
||||||
|
import org.springframework.orm.hibernate.support.HibernateDaoSupport;
|
||||||
|
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link Dao} implementation that uses Hibernate for persistence.
|
||||||
|
*
|
||||||
|
* @author Ben Alex
|
||||||
|
* @version $Id$
|
||||||
|
*/
|
||||||
|
public class DaoHibernate extends HibernateDaoSupport implements Dao,
|
||||||
|
EvictionCapable {
|
||||||
|
//~ Instance fields ========================================================
|
||||||
|
|
||||||
|
/** The class that this instance provides services for */
|
||||||
|
private Class supportsClass;
|
||||||
|
|
||||||
|
//~ Methods ================================================================
|
||||||
|
|
||||||
|
public void setSupportsClass(Class supportClass) {
|
||||||
|
this.supportsClass = supportClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Class getSupportsClass() {
|
||||||
|
return supportsClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PersistableEntity create(PersistableEntity value) {
|
||||||
|
Assert.notNull(value);
|
||||||
|
getHibernateTemplate().save(value);
|
||||||
|
|
||||||
|
return readId(value.getInternalId());
|
||||||
|
}
|
||||||
|
|
||||||
|
public PersistableEntity createOrUpdate(PersistableEntity value) {
|
||||||
|
Assert.notNull(value);
|
||||||
|
|
||||||
|
if (value.getInternalId() == null) {
|
||||||
|
return create(value);
|
||||||
|
} else {
|
||||||
|
return update(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void delete(PersistableEntity value) {
|
||||||
|
Assert.notNull(value);
|
||||||
|
getHibernateTemplate().delete(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void evict(PersistableEntity entity) {
|
||||||
|
Assert.notNull(entity);
|
||||||
|
getHibernateTemplate().evict(entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List findAll() {
|
||||||
|
return getHibernateTemplate().loadAll(supportsClass);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List findId(Collection ids) {
|
||||||
|
Assert.notNull(ids, "Collection of IDs cannot be null");
|
||||||
|
Assert.notEmpty(ids, "There must be some values in the Collection list");
|
||||||
|
|
||||||
|
return (List) getHibernateTemplate().execute(getFindByIdCallback(ids));
|
||||||
|
}
|
||||||
|
|
||||||
|
public PersistableEntity readId(Serializable id) {
|
||||||
|
Assert.notNull(id);
|
||||||
|
|
||||||
|
try {
|
||||||
|
return (PersistableEntity) getHibernateTemplate().load(supportsClass,
|
||||||
|
id);
|
||||||
|
} catch (HibernateObjectRetrievalFailureException notFound) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public PaginatedList scroll(PersistableEntity value, int firstElement,
|
||||||
|
int maxElements, String orderByAsc) {
|
||||||
|
Assert.notNull(value);
|
||||||
|
Assert.hasText(orderByAsc,
|
||||||
|
"An orderByAsc is required (why not use your identity property?)");
|
||||||
|
|
||||||
|
return (PaginatedList) getHibernateTemplate().execute(getFindByValueCallback(
|
||||||
|
value, firstElement, maxElements, Order.asc(orderByAsc)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean supports(Class clazz) {
|
||||||
|
Assert.notNull(clazz);
|
||||||
|
|
||||||
|
return this.supportsClass.equals(clazz);
|
||||||
|
}
|
||||||
|
|
||||||
|
public PersistableEntity update(PersistableEntity value) {
|
||||||
|
Assert.notNull(value);
|
||||||
|
getHibernateTemplate().update(value);
|
||||||
|
|
||||||
|
return readId(value.getInternalId());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Custom initialization behavior. Called by superclass.
|
||||||
|
*
|
||||||
|
* @throws Exception if initialization fails
|
||||||
|
*/
|
||||||
|
protected final void initDao() throws Exception {
|
||||||
|
Assert.notNull(supportsClass, "supportClass is required");
|
||||||
|
Assert.isTrue(PersistableEntity.class.isAssignableFrom(supportsClass),
|
||||||
|
"supportClass is not an implementation of PersistableEntity");
|
||||||
|
initHibernateDao();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allows subclasses to provide custom initialization behaviour. Called
|
||||||
|
* during {@link #initDao()}.
|
||||||
|
*
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
protected void initHibernateDao() throws Exception {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 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 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 Object bean,
|
||||||
|
final int firstElement, final int count, final Order order) {
|
||||||
|
return new HibernateCallback() {
|
||||||
|
public Object doInHibernate(Session session)
|
||||||
|
throws HibernateException {
|
||||||
|
Criteria criteria = session.createCriteria(bean.getClass());
|
||||||
|
|
||||||
|
criteria.addOrder(order);
|
||||||
|
|
||||||
|
ClassMetadata classMetadata = getSessionFactory()
|
||||||
|
.getClassMetadata(bean
|
||||||
|
.getClass());
|
||||||
|
|
||||||
|
/* 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];
|
||||||
|
Object value = classMetadata.getPropertyValue(bean, name);
|
||||||
|
|
||||||
|
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].isPersistentCollectionType()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Type type = classMetadata.getPropertyType(name);
|
||||||
|
|
||||||
|
if (name.equals("version")) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type.equals(Hibernate.STRING)) {
|
||||||
|
// if the property is mapped as String, find partial match
|
||||||
|
criteria.add(Expression.ilike(name,
|
||||||
|
value.toString(), MatchMode.ANYWHERE));
|
||||||
|
} else {
|
||||||
|
// find exact match
|
||||||
|
criteria.add(Expression.eq(name, value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TODO Use Criteria.count() when available in next Hibernate
|
||||||
|
* versions
|
||||||
|
*/
|
||||||
|
int size = criteria.list().size();
|
||||||
|
|
||||||
|
List list = criteria.setFirstResult(firstElement)
|
||||||
|
.setMaxResults(count).list();
|
||||||
|
|
||||||
|
return new PaginatedList(list, firstElement, count, size);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,103 @@
|
||||||
|
/* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package net.sf.acegisecurity.domain.hibernate;
|
||||||
|
|
||||||
|
import net.sf.acegisecurity.domain.validation.IntrospectionManager;
|
||||||
|
|
||||||
|
import net.sf.hibernate.HibernateException;
|
||||||
|
import net.sf.hibernate.SessionFactory;
|
||||||
|
import net.sf.hibernate.metadata.ClassMetadata;
|
||||||
|
import net.sf.hibernate.type.Type;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
|
|
||||||
|
import org.springframework.orm.hibernate.HibernateSystemException;
|
||||||
|
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@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 SessionFactory sessionFactory;
|
||||||
|
|
||||||
|
//~ Methods ================================================================
|
||||||
|
|
||||||
|
public void setSessionFactory(SessionFactory sessionFactory) {
|
||||||
|
this.sessionFactory = sessionFactory;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SessionFactory getSessionFactory() {
|
||||||
|
return this.sessionFactory;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void afterPropertiesSet() throws Exception {
|
||||||
|
Assert.notNull(sessionFactory, "SessionFactory is required");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void obtainImmediateChildren(Object parentObject, List allObjects) {
|
||||||
|
Assert.notNull(parentObject,
|
||||||
|
"Violation of interface contract: parentObject null");
|
||||||
|
Assert.notNull(allObjects,
|
||||||
|
"Violation of interface contract: allObjects null");
|
||||||
|
|
||||||
|
ClassMetadata classMetadata = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
classMetadata = sessionFactory.getClassMetadata(parentObject
|
||||||
|
.getClass());
|
||||||
|
|
||||||
|
if (classMetadata != null) {
|
||||||
|
String[] propertyNames = classMetadata.getPropertyNames();
|
||||||
|
|
||||||
|
for (int i = 0; i < propertyNames.length; i++) {
|
||||||
|
Type propertyType = classMetadata.getPropertyType(propertyNames[i]);
|
||||||
|
|
||||||
|
if (propertyType.isObjectType()) {
|
||||||
|
allObjects.add(classMetadata.getPropertyValue(
|
||||||
|
parentObject, propertyNames[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (HibernateException he) {
|
||||||
|
throw new HibernateSystemException(he);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
<p>Hibernate-specific implementations of the domain subproject interfaces.</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
|
@ -0,0 +1,77 @@
|
||||||
|
/* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package net.sf.acegisecurity.domain.impl;
|
||||||
|
|
||||||
|
import net.sf.acegisecurity.domain.PersistableEntity;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An abstract implementation of {@link
|
||||||
|
* net.sf.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 ================================================================
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 final boolean isNew() {
|
||||||
|
return (getInternalId() == null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 final int getVersion() {
|
||||||
|
return version;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the version numbers. Should only be used by the persistence layer.
|
||||||
|
*
|
||||||
|
* @param version the new version number to use
|
||||||
|
*
|
||||||
|
* @hibernate.version type="integer"
|
||||||
|
*/
|
||||||
|
protected final void setVersion(int version) {
|
||||||
|
this.version = version;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,81 @@
|
||||||
|
/* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package net.sf.acegisecurity.domain.impl;
|
||||||
|
|
||||||
|
import net.sf.acegisecurity.domain.util.CollectionIgnoringReflectionToStringBuilder;
|
||||||
|
|
||||||
|
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
|
||||||
|
* @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().
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @return a clone of the current instance
|
||||||
|
*
|
||||||
|
* @throws IllegalStateException if there are any problems with swallow
|
||||||
|
* cloning
|
||||||
|
*
|
||||||
|
* @see java.lang.Object#clone()
|
||||||
|
* @see BeanUtils#cloneBean(Object)
|
||||||
|
*/
|
||||||
|
public Object clone() {
|
||||||
|
try {
|
||||||
|
return BeanUtils.cloneBean(this);
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error(e);
|
||||||
|
throw new IllegalStateException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delegates to {@link CollectionIgnoringReflectionToStringBuilder}.
|
||||||
|
*
|
||||||
|
* @see java.lang.Object#toString()
|
||||||
|
*/
|
||||||
|
public String toString() {
|
||||||
|
return new CollectionIgnoringReflectionToStringBuilder(this).toString();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,78 @@
|
||||||
|
/* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package net.sf.acegisecurity.domain.impl;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A persistable entity that uses an <code>Integer</code> based identity.
|
||||||
|
*
|
||||||
|
* @author Ben Alex
|
||||||
|
* @version $Id$
|
||||||
|
*/
|
||||||
|
public abstract class PersistableEntityInteger extends AbstractPersistableEntity {
|
||||||
|
//~ Instance fields ========================================================
|
||||||
|
|
||||||
|
private Integer id;
|
||||||
|
|
||||||
|
//~ Methods ================================================================
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DO NOT USE DIRECTLY.
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* Typically only used by the persistence layer, but provided with public
|
||||||
|
* visibility to not limit flexibility.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param id the new instance identity
|
||||||
|
*/
|
||||||
|
public void setId(Integer id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtains the persistence identity of this instance.
|
||||||
|
*
|
||||||
|
* @return the instance's identity
|
||||||
|
*
|
||||||
|
* @hibernate.id generator-class="sequence"
|
||||||
|
*/
|
||||||
|
public Integer getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DO NOT USE DIRECTLY.
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* Use {@link #getId()} instead, as it provides the correct return type.
|
||||||
|
* This method is only provided for use by the persistence layer and to
|
||||||
|
* satisfy the {@link net.sf.acegisecurity.domain.PersistableEntity}
|
||||||
|
* interface contract.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* Internally delegates to {@link #getId()}.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @return the instance's identity
|
||||||
|
*/
|
||||||
|
public Serializable getInternalId() {
|
||||||
|
return this.getId();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,78 @@
|
||||||
|
/* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package net.sf.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 ================================================================
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DO NOT USE DIRECTLY.
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* Typically only used by the persistence layer, but provided with public
|
||||||
|
* visibility to not limit flexibility.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param id the new instance identity
|
||||||
|
*/
|
||||||
|
public void setId(Long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtains the persistence identity of this instance.
|
||||||
|
*
|
||||||
|
* @return the instance's identity
|
||||||
|
*
|
||||||
|
* @hibernate.id generator-class="sequence"
|
||||||
|
*/
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DO NOT USE DIRECTLY.
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* Use {@link #getId()} instead, as it provides the correct return type.
|
||||||
|
* This method is only provided for use by the persistence layer and to
|
||||||
|
* satisfy the {@link net.sf.acegisecurity.domain.PersistableEntity}
|
||||||
|
* interface contract.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* Internally delegates to {@link #getId()}.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @return the instance's identity
|
||||||
|
*/
|
||||||
|
public Serializable getInternalId() {
|
||||||
|
return this.getId();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
/* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package net.sf.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
|
||||||
|
* net.sf.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 {}
|
|
@ -0,0 +1,7 @@
|
||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
<p>Convenient domain object abstract classes, although none are mandatory/required by
|
||||||
|
other packages in this project.</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
<p>Provides tools to assist develop rich domain object models.</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
|
@ -0,0 +1,51 @@
|
||||||
|
/* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package net.sf.acegisecurity.domain.util;
|
||||||
|
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A <code>toString()</code> builder that ignores collections.
|
||||||
|
*
|
||||||
|
* @author Carlos Sanchez
|
||||||
|
* @version $Id$
|
||||||
|
*
|
||||||
|
* @see org.apache.commons.lang.builder.ReflectionToStringBuilder
|
||||||
|
*/
|
||||||
|
public class CollectionIgnoringReflectionToStringBuilder
|
||||||
|
extends ReflectionToStringBuilder {
|
||||||
|
//~ Constructors ===========================================================
|
||||||
|
|
||||||
|
public CollectionIgnoringReflectionToStringBuilder(Object object) {
|
||||||
|
super(object);
|
||||||
|
}
|
||||||
|
|
||||||
|
//~ Methods ================================================================
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the field is a collection and return false in that case.
|
||||||
|
*
|
||||||
|
* @see org.apache.commons.lang.builder.ReflectionToStringBuilder#accept(java.lang.reflect.Field)
|
||||||
|
*/
|
||||||
|
protected boolean accept(Field field) {
|
||||||
|
if (CollectionUtils.isCollection(field.getType())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return super.accept(field);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,162 @@
|
||||||
|
/* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package net.sf.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 ================================================================
|
||||||
|
|
||||||
|
public static boolean isCollection(Class theClass) {
|
||||||
|
return Collection.class.isAssignableFrom(theClass);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isMap(Class theClass) {
|
||||||
|
return Map.class.isAssignableFrom(theClass);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add an object to a <code>Set</code> and return the result.
|
||||||
|
*
|
||||||
|
* @param set
|
||||||
|
* @param object
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static Set add(Set set, Object object) {
|
||||||
|
set.add(object);
|
||||||
|
|
||||||
|
return set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add an object to a <code>List</code> and return the result.
|
||||||
|
*
|
||||||
|
* @param list
|
||||||
|
* @param object
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static List add(List list, Object 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 collection
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*
|
||||||
|
* @throws IllegalArgumentException DOCUMENT ME!
|
||||||
|
*/
|
||||||
|
public static Collection clone(Collection collection) {
|
||||||
|
if (collection == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Class clazz = collection.getClass();
|
||||||
|
Collection clone = null;
|
||||||
|
|
||||||
|
if (List.class.isAssignableFrom(clazz)) {
|
||||||
|
clone = new ArrayList(collection);
|
||||||
|
} else if (SortedSet.class.isAssignableFrom(clazz)) {
|
||||||
|
clone = new TreeSet(collection);
|
||||||
|
} else if (Set.class.isAssignableFrom(clazz)) {
|
||||||
|
clone = new HashSet(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 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 Map clone(Map map) {
|
||||||
|
if (map == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Class clazz = map.getClass();
|
||||||
|
Map clone = null;
|
||||||
|
|
||||||
|
if (SortedMap.class.isAssignableFrom(clazz)) {
|
||||||
|
clone = new TreeMap(map);
|
||||||
|
} else if (Map.class.isAssignableFrom(clazz)) {
|
||||||
|
clone = new HashMap(map);
|
||||||
|
} else {
|
||||||
|
throw new IllegalArgumentException("Unknown map class: " + clazz);
|
||||||
|
}
|
||||||
|
|
||||||
|
return clone;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a <code>List</code> (actually an {@link ArrayList}) with only
|
||||||
|
* that object.
|
||||||
|
*
|
||||||
|
* @param object
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static List newList(Object object) {
|
||||||
|
return add(new ArrayList(1), object);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a <code>Set</code> (actually a {@link HashSet}) with only that
|
||||||
|
* object.
|
||||||
|
*
|
||||||
|
* @param object
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static Set newSet(Object object) {
|
||||||
|
return add(new HashSet(), object);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,67 @@
|
||||||
|
/* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package net.sf.acegisecurity.domain.util;
|
||||||
|
|
||||||
|
import org.apache.commons.lang.builder.ToStringStyle;
|
||||||
|
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
|
||||||
|
import java.text.DateFormat;
|
||||||
|
|
||||||
|
import java.util.Calendar;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Customized Commons Lang <code>ReflectionToStringBuilder</code>.
|
||||||
|
*
|
||||||
|
* @author Carlos Sanchez
|
||||||
|
* @version $Revision$
|
||||||
|
*
|
||||||
|
* @see org.apache.commons.lang.builder.ReflectionToStringBuilder
|
||||||
|
*/
|
||||||
|
public class ReflectionToStringBuilder
|
||||||
|
extends org.apache.commons.lang.builder.ReflectionToStringBuilder {
|
||||||
|
//~ Static fields/initializers =============================================
|
||||||
|
|
||||||
|
private static DateFormat formatter = DateFormat.getDateTimeInstance();
|
||||||
|
|
||||||
|
//~ Constructors ===========================================================
|
||||||
|
|
||||||
|
public ReflectionToStringBuilder(Object object) {
|
||||||
|
super(object, ToStringStyle.MULTI_LINE_STYLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
//~ Methods ================================================================
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
<p>Utilities useful in the domain package.</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
|
@ -0,0 +1,57 @@
|
||||||
|
/* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package net.sf.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;
|
||||||
|
}
|
|
@ -0,0 +1,50 @@
|
||||||
|
/* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package net.sf.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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,55 @@
|
||||||
|
/* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package net.sf.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 allObjects);
|
||||||
|
}
|
|
@ -0,0 +1,115 @@
|
||||||
|
/* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package net.sf.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 supportsClass;
|
||||||
|
private String[] methods = {"create", "update"};
|
||||||
|
|
||||||
|
//~ Constructors ===========================================================
|
||||||
|
|
||||||
|
public ValidationAdvisor(ValidationInterceptor advice) {
|
||||||
|
super(advice);
|
||||||
|
|
||||||
|
if (advice == null) {
|
||||||
|
throw new AopConfigException(
|
||||||
|
"Cannot construct a BindAndValidateAdvisor using a "
|
||||||
|
+ "null BindAndValidateInterceptor");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//~ Methods ================================================================
|
||||||
|
|
||||||
|
public void setMethods(String[] methods) {
|
||||||
|
this.methods = methods;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String[] getMethods() {
|
||||||
|
return methods;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSupportsClass(Class clazz) {
|
||||||
|
this.supportsClass = clazz;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Class getSupportsClass() {
|
||||||
|
return supportsClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,107 @@
|
||||||
|
/* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package net.sf.acegisecurity.domain.validation;
|
||||||
|
|
||||||
|
import net.sf.acegisecurity.domain.PersistableEntity;
|
||||||
|
import net.sf.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 net.sf.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 setArgumentClasses(Class[] argumentClasses) {
|
||||||
|
this.argumentClasses = argumentClasses;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Class[] getArgumentClasses() {
|
||||||
|
return argumentClasses;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setValidationManager(ValidationManager validationManager) {
|
||||||
|
this.validationManager = validationManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ValidationManager getValidationManager() {
|
||||||
|
return validationManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 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();
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,49 @@
|
||||||
|
/* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package net.sf.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;
|
||||||
|
}
|
|
@ -0,0 +1,254 @@
|
||||||
|
/* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package net.sf.acegisecurity.domain.validation;
|
||||||
|
|
||||||
|
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
|
||||||
|
* @version $Id$
|
||||||
|
*/
|
||||||
|
public class ValidationManagerImpl implements InitializingBean,
|
||||||
|
ValidationManager {
|
||||||
|
//~ Instance fields ========================================================
|
||||||
|
|
||||||
|
protected final Log logger = LogFactory.getLog(getClass());
|
||||||
|
private IntrospectionManager introspectionManager;
|
||||||
|
private List validators;
|
||||||
|
private boolean strictValidation = true;
|
||||||
|
|
||||||
|
//~ Methods ================================================================
|
||||||
|
|
||||||
|
public void setIntrospectionManager(
|
||||||
|
IntrospectionManager introspectionManager) {
|
||||||
|
this.introspectionManager = introspectionManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IntrospectionManager getIntrospectionManager() {
|
||||||
|
return introspectionManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates whether a {@link ValidatorNotFoundException} should be thrown
|
||||||
|
* if any domain object does not have a corresponding
|
||||||
|
* <code>Validator</code> defined against the {@link #validators}.
|
||||||
|
*
|
||||||
|
* <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 boolean isStrictValidation() {
|
||||||
|
return strictValidation;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the {@link Validator} objects to be used.
|
||||||
|
*
|
||||||
|
* @param newList that should be used for validation.
|
||||||
|
*/
|
||||||
|
public void setValidators(List newList) {
|
||||||
|
Assert.notNull(newList, "A list of Validators is required");
|
||||||
|
Assert.isTrue(newList.size() > 0,
|
||||||
|
"At least one Validator must be defined");
|
||||||
|
|
||||||
|
Iterator iter = newList.iterator();
|
||||||
|
|
||||||
|
while (iter.hasNext()) {
|
||||||
|
Object currentObject = null;
|
||||||
|
currentObject = iter.next();
|
||||||
|
Assert.isInstanceOf(Validator.class, currentObject,
|
||||||
|
"Validator '" + currentObject
|
||||||
|
+ "' must be an instance of Validator");
|
||||||
|
}
|
||||||
|
|
||||||
|
this.validators = newList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List getValidators() {
|
||||||
|
return this.validators;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void afterPropertiesSet() throws Exception {
|
||||||
|
Assert.notNull(validators, "A list of Validators is required");
|
||||||
|
Assert.isTrue(validators.size() > 0,
|
||||||
|
"At least one Validator must be defined");
|
||||||
|
Assert.notNull(introspectionManager,
|
||||||
|
"An IntrospectionManager is required");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 add self
|
||||||
|
List allObjects = new Vector();
|
||||||
|
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 iter = allObjects.iterator();
|
||||||
|
|
||||||
|
while (iter.hasNext()) {
|
||||||
|
Object currentDomainObject = iter.next();
|
||||||
|
Class clazz = currentDomainObject.getClass();
|
||||||
|
|
||||||
|
try {
|
||||||
|
Errors errors = new BindException(currentDomainObject,
|
||||||
|
clazz.getName());
|
||||||
|
Validator v = findValidator(clazz);
|
||||||
|
|
||||||
|
// Call bindSupport() if this class wishes
|
||||||
|
BindBeforeValidationUtils.bindIfRequired(currentDomainObject);
|
||||||
|
|
||||||
|
// Perform validation
|
||||||
|
v.validate(currentDomainObject, errors);
|
||||||
|
|
||||||
|
// Handle validation outcome
|
||||||
|
if (errors.getErrorCount() == 0) {
|
||||||
|
if (logger.isDebugEnabled()) {
|
||||||
|
logger.debug("Validated '" + clazz + "' successfully");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (logger.isDebugEnabled()) {
|
||||||
|
logger.debug("Validated '" + clazz
|
||||||
|
+ "' 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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Validator findValidator(Class clazz)
|
||||||
|
throws ValidatorNotFoundException {
|
||||||
|
Assert.notNull(clazz, "Class cannot be null");
|
||||||
|
|
||||||
|
Iterator iter = validators.iterator();
|
||||||
|
|
||||||
|
while (iter.hasNext()) {
|
||||||
|
Validator validator = (Validator) iter.next();
|
||||||
|
|
||||||
|
if (validator.supports(clazz)) {
|
||||||
|
return validator;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new ValidatorNotFoundException("No Validator found for class '"
|
||||||
|
+ clazz + "'");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 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");
|
||||||
|
|
||||||
|
// Add immediate children of this domain object
|
||||||
|
List currentChildren = new Vector();
|
||||||
|
introspectionManager.obtainImmediateChildren(parentObject,
|
||||||
|
currentChildren);
|
||||||
|
|
||||||
|
// Add the children
|
||||||
|
allObjects.addAll(currentChildren);
|
||||||
|
|
||||||
|
// Now iterate the children, adding their children to the object list
|
||||||
|
Iterator childrenIter = currentChildren.iterator();
|
||||||
|
|
||||||
|
while (childrenIter.hasNext()) {
|
||||||
|
Object childObject = childrenIter.next();
|
||||||
|
|
||||||
|
if (childObject != null) {
|
||||||
|
obtainAllChildren(childObject, allObjects);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,51 @@
|
||||||
|
/* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package net.sf.acegisecurity.domain.validation;
|
||||||
|
|
||||||
|
import net.sf.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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,46 @@
|
||||||
|
<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} should be
|
||||||
|
used against each of your data access object (DAO) mutator methods, such as
|
||||||
|
<code>SomeDao.create(Object)</code> and <code>SomeDao.update(Object)</code>.
|
||||||
|
The interceptor will cause the <code>Object</code> to be presented to the
|
||||||
|
<code>ValidationManager</code>, thus ensuring the domain object instance is in
|
||||||
|
a valid state before being persisted.</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. If using an ORM tool such as
|
||||||
|
Hibernate, it is recommended your <code>Validator</code>s subclass a common
|
||||||
|
abstract parent that provides an <code>evict(Object)</code> and
|
||||||
|
<code>evict(Collection)</code> method. That way your <code>Validator</code>s
|
||||||
|
can utilise standard services layer or DAO methods as required to retrieve
|
||||||
|
other domain objects, and flush them from the session cache afterwards. Whilst
|
||||||
|
this is more a <code>Validator</code> design choice than something mandated by
|
||||||
|
this package, we have found it a worthwhile pattern in real-world applications.
|
||||||
|
</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
|
@ -63,7 +63,7 @@ maven.license.licenseFile=${rootdir}/LICENSE.txt
|
||||||
|
|
||||||
# multiproject
|
# multiproject
|
||||||
maven.multiproject.basedir=${rootdir}
|
maven.multiproject.basedir=${rootdir}
|
||||||
maven.multiproject.includes=core/project.xml,adapters/*/project.xml,samples/*/project.xml
|
maven.multiproject.includes=core/project.xml,adapters/*/project.xml,samples/*/project.xml,domain/project.xml
|
||||||
|
|
||||||
# multichanges
|
# multichanges
|
||||||
maven.multichanges.basedir=${maven.multiproject.basedir}
|
maven.multichanges.basedir=${maven.multiproject.basedir}
|
||||||
|
|
Loading…
Reference in New Issue