Initial commit.
This commit is contained in:
parent
046dd2611c
commit
cf241fb9ae
|
@ -1,6 +1,10 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<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="samples/attributes/src/main/resources"/>
|
||||
<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/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/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"/>
|
||||
</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
|
||||
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
|
||||
maven.multichanges.basedir=${maven.multiproject.basedir}
|
||||
|
|
Loading…
Reference in New Issue