[jboss-cvs] Picketlink SVN: r740 - in idm/trunk: picketlink-idm-jpa and 16 other directories.

jboss-cvs-commits at lists.jboss.org jboss-cvs-commits at lists.jboss.org
Mon Feb 7 05:18:43 EST 2011


Author: bdaw
Date: 2011-02-07 05:18:43 -0500 (Mon, 07 Feb 2011)
New Revision: 740

Added:
   idm/trunk/picketlink-idm-jpa/
   idm/trunk/picketlink-idm-jpa/pom.xml
   idm/trunk/picketlink-idm-jpa/src/
   idm/trunk/picketlink-idm-jpa/src/main/
   idm/trunk/picketlink-idm-jpa/src/main/java/
   idm/trunk/picketlink-idm-jpa/src/main/java/org/
   idm/trunk/picketlink-idm-jpa/src/main/java/org/picketlink/
   idm/trunk/picketlink-idm-jpa/src/main/java/org/picketlink/idm/
   idm/trunk/picketlink-idm-jpa/src/main/java/org/picketlink/idm/impl/
   idm/trunk/picketlink-idm-jpa/src/main/java/org/picketlink/idm/impl/model/
   idm/trunk/picketlink-idm-jpa/src/main/java/org/picketlink/idm/impl/model/jpa/
   idm/trunk/picketlink-idm-jpa/src/main/java/org/picketlink/idm/impl/model/jpa/IdentityObject.java
   idm/trunk/picketlink-idm-jpa/src/main/java/org/picketlink/idm/impl/model/jpa/IdentityObjectCredential.java
   idm/trunk/picketlink-idm-jpa/src/main/java/org/picketlink/idm/impl/model/jpa/IdentityObjectCredentialType.java
   idm/trunk/picketlink-idm-jpa/src/main/java/org/picketlink/idm/impl/model/jpa/IdentityObjectRelationship.java
   idm/trunk/picketlink-idm-jpa/src/main/java/org/picketlink/idm/impl/model/jpa/IdentityObjectRelationshipType.java
   idm/trunk/picketlink-idm-jpa/src/main/java/org/picketlink/idm/impl/model/jpa/IdentityObjectType.java
   idm/trunk/picketlink-idm-jpa/src/main/java/org/picketlink/idm/impl/model/jpa/IdentityRoleName.java
   idm/trunk/picketlink-idm-jpa/src/main/java/org/picketlink/idm/impl/model/jpa/annotations/
   idm/trunk/picketlink-idm-jpa/src/main/java/org/picketlink/idm/impl/store/
   idm/trunk/picketlink-idm-jpa/src/main/java/org/picketlink/idm/impl/store/jpa/
   idm/trunk/picketlink-idm-jpa/src/main/java/org/picketlink/idm/impl/store/jpa/IdentityObjectImpl.java
   idm/trunk/picketlink-idm-jpa/src/main/java/org/picketlink/idm/impl/store/jpa/IdentityObjectRelationshipImpl.java
   idm/trunk/picketlink-idm-jpa/src/main/java/org/picketlink/idm/impl/store/jpa/IdentityObjectRelationshipTypeImpl.java
   idm/trunk/picketlink-idm-jpa/src/main/java/org/picketlink/idm/impl/store/jpa/IdentityObjectTypeImpl.java
   idm/trunk/picketlink-idm-jpa/src/main/java/org/picketlink/idm/impl/store/jpa/IdentityProperty.java
   idm/trunk/picketlink-idm-jpa/src/main/java/org/picketlink/idm/impl/store/jpa/IdentitySessionProducer.java
   idm/trunk/picketlink-idm-jpa/src/main/java/org/picketlink/idm/impl/store/jpa/IdentityStoreConfiguration.java
   idm/trunk/picketlink-idm-jpa/src/main/java/org/picketlink/idm/impl/store/jpa/JpaIdentityStore.java
   idm/trunk/picketlink-idm-jpa/src/main/java/org/picketlink/idm/impl/store/jpa/JpaIdentityStoreConfiguration.java
   idm/trunk/picketlink-idm-jpa/src/main/java/org/picketlink/idm/impl/store/jpa/JpaIdentityStoreSessionImpl.java
   idm/trunk/picketlink-idm-jpa/src/main/java/org/picketlink/idm/impl/store/jpa/PropertyType.java
   idm/trunk/picketlink-idm-jpa/src/main/resources/
   idm/trunk/picketlink-idm-jpa/src/test/
   idm/trunk/picketlink-idm-jpa/src/test/java/
   idm/trunk/picketlink-idm-jpa/src/test/java/org/
   idm/trunk/picketlink-idm-jpa/src/test/java/org/picketlink/
   idm/trunk/picketlink-idm-jpa/src/test/java/org/picketlink/idm/
   idm/trunk/picketlink-idm-jpa/src/test/java/org/picketlink/idm/impl/
   idm/trunk/picketlink-idm-jpa/src/test/resources/
Modified:
   idm/trunk/pom.xml
Log:
initial import of jpa store impl

Added: idm/trunk/picketlink-idm-jpa/pom.xml
===================================================================
--- idm/trunk/picketlink-idm-jpa/pom.xml	                        (rev 0)
+++ idm/trunk/picketlink-idm-jpa/pom.xml	2011-02-07 10:18:43 UTC (rev 740)
@@ -0,0 +1,127 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+   <parent>
+      <groupId>org.picketlink.idm</groupId>
+      <artifactId>picketlink-idm-parent</artifactId>
+      <version>1.3.0.Alpha01-SNAPSHOT</version>
+      <relativePath>../parent</relativePath>
+   </parent>
+   <modelVersion>4.0.0</modelVersion>
+   <artifactId>picketlink-idm-jpa</artifactId>
+  <version>1.3.0.Alpha01-SNAPSHOT</version>
+   <packaging>jar</packaging>
+   <name>PicketLink IDM JPA</name>
+   <url>http://labs.jboss.org/portal/jbosssecurity/</url>
+   <description>PicketLink IDM JPA</description>
+   <licenses>
+      <license>
+         <name>lgpl</name>
+         <url>http://repository.jboss.com/licenses/lgpl.txt</url>
+      </license>
+   </licenses>
+   <organization>
+      <name>JBoss Inc.</name>
+      <url>http://www.jboss.org</url>
+   </organization>
+
+   <dependencies>
+      <dependency>
+         <groupId>org.picketlink.idm</groupId>
+         <artifactId>picketlink-idm-core</artifactId>
+         <version>${project.version}</version>
+      </dependency>
+
+      <dependency>
+         <groupId>org.jboss.seam.solder</groupId>
+         <artifactId>seam-solder</artifactId>
+         <version>3.0.0.Beta2</version>
+      </dependency>
+
+      <!--<dependency>-->
+         <!--<groupId>javax.persistence</groupId>-->
+         <!--<artifactId>persistence-api</artifactId>-->
+         <!--<version>1.0</version>-->
+      <!--</dependency>-->
+      <dependency>
+         <groupId>org.hibernate.javax.persistence</groupId>
+         <artifactId>hibernate-jpa-2.0-api</artifactId>
+         <version>1.0.0.Final</version>
+      </dependency>
+
+
+      <!-- hibernate -->
+      <!--<dependency>-->
+         <!--<groupId>org.hibernate</groupId>-->
+         <!--<artifactId>hibernate-core</artifactId>-->
+         <!--<version>3.3.2.GA</version>-->
+      <!--</dependency>-->
+      <!--<dependency>-->
+         <!--<groupId>org.hibernate</groupId>-->
+         <!--<artifactId>hibernate-core</artifactId>-->
+         <!--<version>3.3.2.GA</version>-->
+      <!--</dependency>-->
+      <!--<dependency>-->
+         <!--<groupId>org.hibernate</groupId>-->
+         <!--<artifactId>hibernate-annotations</artifactId>-->
+         <!--<version>3.4.0.GA</version>-->
+      <!--</dependency>-->
+      <!--Javassist as Hibernate's bytecode provider-->
+      <!--<dependency>-->
+         <!--<groupId>javassist</groupId>-->
+         <!--<artifactId>javassist</artifactId>-->
+         <!--<version>3.8.0.GA</version>-->
+      <!--</dependency>-->
+
+      <!--<dependency>-->
+         <!--<groupId>org.hibernate</groupId>-->
+         <!--<artifactId>hibernate-cglib-repack</artifactId>-->
+         <!--<version>2.1_3</version>-->
+      <!--</dependency>-->
+
+
+      <!-- Hibernate logging set up -->
+      <!--<dependency>-->
+         <!--<groupId>org.slf4j</groupId>-->
+         <!--<artifactId>slf4j-log4j12</artifactId>-->
+         <!--<version>1.5.2</version>-->
+      <!--</dependency>-->
+      <!--<dependency>-->
+         <!--<groupId>log4j</groupId>-->
+         <!--<artifactId>log4j</artifactId>-->
+         <!--<version>1.2.14</version>-->
+      <!--</dependency>-->
+
+      <!--<dependency>-->
+         <!--<groupId>junit</groupId>-->
+         <!--<artifactId>junit</artifactId>-->
+         <!--<scope>test</scope>-->
+      <!--</dependency>-->
+      
+   </dependencies>
+
+
+
+   <build>
+      <plugins>
+         <plugin>
+            <groupId>org.apache.maven.plugins</groupId>
+            <artifactId>maven-surefire-plugin</artifactId>
+            <version>2.4.3</version>
+            <configuration>
+               <systemProperties>
+                  <property>
+                     <name>dataSourceName</name>
+                     <value>${dataSourceName}</value>
+                  </property>
+                  <property>
+                     <name>directoryName</name>
+                     <value>${directoryName}</value>
+                  </property>
+               </systemProperties>
+            </configuration>
+         </plugin>
+
+      </plugins>
+   </build>
+
+
+</project>

Added: idm/trunk/picketlink-idm-jpa/src/main/java/org/picketlink/idm/impl/model/jpa/IdentityObject.java
===================================================================
--- idm/trunk/picketlink-idm-jpa/src/main/java/org/picketlink/idm/impl/model/jpa/IdentityObject.java	                        (rev 0)
+++ idm/trunk/picketlink-idm-jpa/src/main/java/org/picketlink/idm/impl/model/jpa/IdentityObject.java	2011-02-07 10:18:43 UTC (rev 740)
@@ -0,0 +1,61 @@
+package org.picketlink.idm.impl.model.jpa;
+
+import java.io.Serializable;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+
+import org.picketlink.idm.impl.store.jpa.IdentityProperty;
+import org.picketlink.idm.impl.store.jpa.PropertyType;
+
+/**
+ * This entity contains identity objects, e.g. users and groups 
+ * 
+ * @author Shane Bryzak
+ */
+ at Entity
+public class IdentityObject implements Serializable
+{
+   private static final long serialVersionUID = -4623023512038059728L;
+   
+   private Long id;
+   private String name;
+   private IdentityObjectType type;
+   
+   @Id @GeneratedValue
+   public Long getId()
+   {
+      return id;
+   }
+   
+   public void setId(Long id)
+   {
+      this.id = id;
+   }
+   
+   public String getName()
+   {
+      return name;
+   }
+   
+   public void setName(String name)
+   {
+      this.name = name;
+   }
+   
+   @ManyToOne @IdentityProperty(PropertyType.TYPE)
+   @JoinColumn(name = "IDENTITY_OBJECT_TYPE_ID")
+   public IdentityObjectType getType()
+   {
+      return type;
+   }
+   
+   public void setType(IdentityObjectType type)
+   {
+      this.type = type;
+   }
+
+}

Added: idm/trunk/picketlink-idm-jpa/src/main/java/org/picketlink/idm/impl/model/jpa/IdentityObjectCredential.java
===================================================================
--- idm/trunk/picketlink-idm-jpa/src/main/java/org/picketlink/idm/impl/model/jpa/IdentityObjectCredential.java	                        (rev 0)
+++ idm/trunk/picketlink-idm-jpa/src/main/java/org/picketlink/idm/impl/model/jpa/IdentityObjectCredential.java	2011-02-07 10:18:43 UTC (rev 740)
@@ -0,0 +1,73 @@
+package org.picketlink.idm.impl.model.jpa;
+
+import java.io.Serializable;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+
+import org.picketlink.idm.impl.store.jpa.IdentityProperty;
+import org.picketlink.idm.impl.store.jpa.PropertyType;
+
+/**
+ * Holds credential values
+ * 
+ * @author Shane Bryzak
+ */
+ at Entity
+public class IdentityObjectCredential implements Serializable
+{
+   private static final long serialVersionUID = 1359292319831314803L;
+   
+   private Long id;
+   private IdentityObject identityObject;
+   private IdentityObjectCredentialType type;
+   private String value;
+   
+   @Id @GeneratedValue
+   public Long getId()
+   {
+      return id;
+   }
+   
+   public void setId(Long id)
+   {
+      this.id = id;
+   }
+   
+   @ManyToOne @JoinColumn(name = "IDENTITY_OBJECT_ID")
+   public IdentityObject getIdentityObject()
+   {
+      return identityObject;
+   }
+   
+   public void setIdentityObject(IdentityObject identityObject)
+   {
+      this.identityObject = identityObject;
+   }
+   
+   @ManyToOne @IdentityProperty(PropertyType.TYPE)
+   @JoinColumn(name = "CREDENTIAL_TYPE_ID")
+   public IdentityObjectCredentialType getType()
+   {
+      return type;
+   }
+   
+   public void setType(IdentityObjectCredentialType type)
+   {
+      this.type = type;
+   }
+   
+   @IdentityProperty(PropertyType.VALUE)
+   public String getValue()
+   {
+      return value;
+   }
+   
+   public void setValue(String value)
+   {
+      this.value = value;
+   }
+}

Added: idm/trunk/picketlink-idm-jpa/src/main/java/org/picketlink/idm/impl/model/jpa/IdentityObjectCredentialType.java
===================================================================
--- idm/trunk/picketlink-idm-jpa/src/main/java/org/picketlink/idm/impl/model/jpa/IdentityObjectCredentialType.java	                        (rev 0)
+++ idm/trunk/picketlink-idm-jpa/src/main/java/org/picketlink/idm/impl/model/jpa/IdentityObjectCredentialType.java	2011-02-07 10:18:43 UTC (rev 740)
@@ -0,0 +1,46 @@
+package org.picketlink.idm.impl.model.jpa;
+
+import java.io.Serializable;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+
+import org.picketlink.idm.impl.store.jpa.IdentityProperty;
+import org.picketlink.idm.impl.store.jpa.PropertyType;
+
+/**
+ * Lookup table containing credential types
+ * 
+ * @author Shane Bryzak
+ */
+ at Entity
+public class IdentityObjectCredentialType implements Serializable
+{
+   private static final long serialVersionUID = 282711089697868242L;
+   
+   private Long id;
+   private String name;
+   
+   @Id @GeneratedValue
+   public Long getId()
+   {
+      return id;
+   }
+   
+   public void setId(Long id)
+   {
+      this.id = id;
+   }
+   
+   @IdentityProperty(PropertyType.NAME)
+   public String getName()
+   {
+      return name;
+   }
+   
+   public void setName(String name)
+   {
+      this.name = name;
+   }
+}

Added: idm/trunk/picketlink-idm-jpa/src/main/java/org/picketlink/idm/impl/model/jpa/IdentityObjectRelationship.java
===================================================================
--- idm/trunk/picketlink-idm-jpa/src/main/java/org/picketlink/idm/impl/model/jpa/IdentityObjectRelationship.java	                        (rev 0)
+++ idm/trunk/picketlink-idm-jpa/src/main/java/org/picketlink/idm/impl/model/jpa/IdentityObjectRelationship.java	2011-02-07 10:18:43 UTC (rev 740)
@@ -0,0 +1,83 @@
+package org.picketlink.idm.impl.model.jpa;
+
+import java.io.Serializable;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+
+import org.picketlink.idm.impl.store.jpa.IdentityProperty;
+import org.picketlink.idm.impl.store.jpa.PropertyType;
+
+/**
+ * Contains relationships between identities
+ * 
+ * @author Shane Bryzak
+ */
+ at Entity
+public class IdentityObjectRelationship implements Serializable
+{
+   private static final long serialVersionUID = -5254503795105571898L;
+   
+   private Long id;
+   private String name;
+   private IdentityObjectRelationshipType relationshipType;
+   private IdentityObject from;
+   private IdentityObject to;
+   
+   @Id @GeneratedValue
+   public Long getId()
+   {
+      return id;
+   }
+   
+   public void setId(Long id)
+   {
+      this.id = id;
+   }
+   
+   public String getName()
+   {
+      return name;
+   }
+   
+   public void setName(String name)
+   {
+      this.name = name;
+   }
+   
+   @ManyToOne @IdentityProperty(PropertyType.TYPE) @JoinColumn(name = "RELATIONSHIP_TYPE_ID")
+   public IdentityObjectRelationshipType getRelationshipType()
+   {
+      return relationshipType;
+   }
+   
+   public void setRelationshipType(IdentityObjectRelationshipType relationshipType)
+   {
+      this.relationshipType = relationshipType;
+   }
+
+   @ManyToOne @IdentityProperty(PropertyType.RELATIONSHIP_FROM) @JoinColumn(name = "FROM_IDENTITY_ID")
+   public IdentityObject getFrom()
+   {
+      return from;
+   }
+   
+   public void setFrom(IdentityObject from)
+   {
+      this.from = from;
+   }
+
+   @ManyToOne @IdentityProperty(PropertyType.RELATIONSHIP_TO) @JoinColumn(name = "TO_IDENTITY_ID")
+   public IdentityObject getTo()
+   {
+      return to;
+   }
+   
+   public void setTo(IdentityObject to)
+   {
+      this.to = to;
+   }
+}

Added: idm/trunk/picketlink-idm-jpa/src/main/java/org/picketlink/idm/impl/model/jpa/IdentityObjectRelationshipType.java
===================================================================
--- idm/trunk/picketlink-idm-jpa/src/main/java/org/picketlink/idm/impl/model/jpa/IdentityObjectRelationshipType.java	                        (rev 0)
+++ idm/trunk/picketlink-idm-jpa/src/main/java/org/picketlink/idm/impl/model/jpa/IdentityObjectRelationshipType.java	2011-02-07 10:18:43 UTC (rev 740)
@@ -0,0 +1,46 @@
+package org.picketlink.idm.impl.model.jpa;
+
+import java.io.Serializable;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+
+import org.picketlink.idm.impl.store.jpa.IdentityProperty;
+import org.picketlink.idm.impl.store.jpa.PropertyType;
+
+/**
+ * Lookup table containing relationship types
+ * 
+ * @author Shane Bryzak
+ */
+ at Entity
+public class IdentityObjectRelationshipType implements Serializable
+{
+   private static final long serialVersionUID = -67640567413388470L;
+   
+   private Long id;
+   private String name;
+   
+   @Id @GeneratedValue
+   public Long getId()
+   {
+      return id;
+   }
+   
+   public void setId(Long id)
+   {
+      this.id = id;
+   }
+   
+   @IdentityProperty(PropertyType.NAME)
+   public String getName()
+   {
+      return name;
+   }
+   
+   public void setName(String name)
+   {
+      this.name = name;
+   }
+}

Added: idm/trunk/picketlink-idm-jpa/src/main/java/org/picketlink/idm/impl/model/jpa/IdentityObjectType.java
===================================================================
--- idm/trunk/picketlink-idm-jpa/src/main/java/org/picketlink/idm/impl/model/jpa/IdentityObjectType.java	                        (rev 0)
+++ idm/trunk/picketlink-idm-jpa/src/main/java/org/picketlink/idm/impl/model/jpa/IdentityObjectType.java	2011-02-07 10:18:43 UTC (rev 740)
@@ -0,0 +1,46 @@
+package org.picketlink.idm.impl.model.jpa;
+
+import java.io.Serializable;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+
+import org.picketlink.idm.impl.store.jpa.IdentityProperty;
+import org.picketlink.idm.impl.store.jpa.PropertyType;
+
+/**
+ * A lookup table containing identity object types
+ *  
+ * @author Shane Bryzak
+ */
+ at Entity
+public class IdentityObjectType implements Serializable
+{
+   private static final long serialVersionUID = -8333008038699510742L;
+   
+   private Long id;
+   private String name;
+   
+   @Id @GeneratedValue
+   public Long getId()
+   {
+      return id;
+   }
+   
+   public void setId(Long id)
+   {
+      this.id = id;
+   }
+   
+   @IdentityProperty(PropertyType.NAME)
+   public String getName()
+   {
+      return name;
+   }
+   
+   public void setName(String name)
+   {
+      this.name = name;
+   }
+}

Added: idm/trunk/picketlink-idm-jpa/src/main/java/org/picketlink/idm/impl/model/jpa/IdentityRoleName.java
===================================================================
--- idm/trunk/picketlink-idm-jpa/src/main/java/org/picketlink/idm/impl/model/jpa/IdentityRoleName.java	                        (rev 0)
+++ idm/trunk/picketlink-idm-jpa/src/main/java/org/picketlink/idm/impl/model/jpa/IdentityRoleName.java	2011-02-07 10:18:43 UTC (rev 740)
@@ -0,0 +1,42 @@
+package org.picketlink.idm.impl.model.jpa;
+
+import java.io.Serializable;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+
+/**
+ * This is a simple lookup table containing role names
+ * 
+ * @author Shane Bryzak
+ */
+ at Entity
+public class IdentityRoleName implements Serializable
+{
+   private static final long serialVersionUID = 8775236263787825703L;
+   
+   private Long id;
+   private String name;
+   
+   @Id @GeneratedValue
+   public Long getId()
+   {
+      return id;
+   }
+   
+   public void setId(Long id)
+   {
+      this.id = id;
+   }
+   
+   public String getName()
+   {
+      return name;
+   }
+   
+   public void setName(String name)
+   {
+      this.name = name;
+   }
+}

Added: idm/trunk/picketlink-idm-jpa/src/main/java/org/picketlink/idm/impl/store/jpa/IdentityObjectImpl.java
===================================================================
--- idm/trunk/picketlink-idm-jpa/src/main/java/org/picketlink/idm/impl/store/jpa/IdentityObjectImpl.java	                        (rev 0)
+++ idm/trunk/picketlink-idm-jpa/src/main/java/org/picketlink/idm/impl/store/jpa/IdentityObjectImpl.java	2011-02-07 10:18:43 UTC (rev 740)
@@ -0,0 +1,72 @@
+package org.picketlink.idm.impl.store.jpa;
+
+
+import java.io.Serializable;
+
+import org.picketlink.idm.common.exception.PolicyValidationException;
+import org.picketlink.idm.spi.model.IdentityObject;
+import org.picketlink.idm.spi.model.IdentityObjectType;
+
+/**
+ * Based implementation of IdentityObject
+ * 
+ * @author Shane Bryzak
+ */
+public class IdentityObjectImpl implements IdentityObject, Serializable
+{
+   private static final long serialVersionUID = -7880202628037808071L;
+   
+   private String id;
+   private String name;
+   private IdentityObjectType type;
+   
+   public IdentityObjectImpl(String id, String name, IdentityObjectType type)
+   {
+      if (name == null) throw new IllegalArgumentException("IdentityObject.name cannot be null");
+      if (type == null) throw new IllegalArgumentException("IdentityObject.identityType cannot be null");
+      
+      this.id = id;
+      this.name = name;
+      this.type = type;
+   }
+
+   public String getId()
+   {
+      return id;
+   }
+
+   public IdentityObjectType getIdentityType()
+   {
+      return type;
+   }
+
+   public String getName()
+   {
+      return name;
+   }
+
+   public void validatePolicy() throws PolicyValidationException
+   {
+
+   }
+   
+   @Override
+   public boolean equals(Object value)
+   {
+      if (!(value instanceof IdentityObject)) return false;
+      IdentityObject other = (IdentityObject) value;
+      
+      return (id != null ? id.equals(other.getId()) : other.getId() == null) && 
+             name.equals(other.getName()) &&
+             type.equals(other.getIdentityType());
+   }
+   
+   @Override
+   public int hashCode()
+   {
+      int hash = 0;
+      if (id != null) hash ^= (id.hashCode() * 17);
+      hash ^= (name.hashCode() * 29) ^ (type.hashCode() * 37);      
+      return hash;
+   }
+}

Added: idm/trunk/picketlink-idm-jpa/src/main/java/org/picketlink/idm/impl/store/jpa/IdentityObjectRelationshipImpl.java
===================================================================
--- idm/trunk/picketlink-idm-jpa/src/main/java/org/picketlink/idm/impl/store/jpa/IdentityObjectRelationshipImpl.java	                        (rev 0)
+++ idm/trunk/picketlink-idm-jpa/src/main/java/org/picketlink/idm/impl/store/jpa/IdentityObjectRelationshipImpl.java	2011-02-07 10:18:43 UTC (rev 740)
@@ -0,0 +1,89 @@
+package org.picketlink.idm.impl.store.jpa;
+
+
+import java.io.Serializable;
+
+import org.picketlink.idm.spi.model.IdentityObject;
+import org.picketlink.idm.spi.model.IdentityObjectRelationship;
+import org.picketlink.idm.spi.model.IdentityObjectRelationshipType;
+
+/**
+ * 
+ * @author Shane Bryzak
+ */
+public class IdentityObjectRelationshipImpl implements IdentityObjectRelationship, Serializable
+{
+   private static final long serialVersionUID = 487517126125658201L;
+   
+   private IdentityObject fromIdentityObject;
+   private IdentityObject toIdentityObject;
+   private String name;
+   private IdentityObjectRelationshipType type;
+   
+   public IdentityObjectRelationshipImpl(IdentityObject fromIdentityObject,
+         IdentityObject toIdentityObject, String name,
+         IdentityObjectRelationshipType type)
+   {
+      if (fromIdentityObject == null) throw new IllegalArgumentException("IdentityObjectRelationship.fromIdentityObject cannot be null.");
+      if (toIdentityObject == null) throw new IllegalArgumentException("IdentityObjectRelationship.toIdentityObject cannot be null.");
+      if (type == null) throw new IllegalArgumentException("IdentityObjectRelationship.type cannot be null.");
+      
+      this.fromIdentityObject = fromIdentityObject;
+      this.toIdentityObject = toIdentityObject;
+      this.name = name;
+      this.type = type;
+   }
+
+   public IdentityObject getFromIdentityObject()
+   {
+      return fromIdentityObject;
+   }
+
+   public IdentityObject getToIdentityObject()
+   {
+      return toIdentityObject;
+   }   
+
+   public String getName()
+   {
+      return name;
+   }
+
+   public IdentityObjectRelationshipType getType()
+   {
+      return type;
+   }
+   
+   @Override
+   public boolean equals(Object value)
+   {
+      if (!(value instanceof IdentityObjectRelationship)) return false;
+      IdentityObjectRelationship other = (IdentityObjectRelationship) value;
+      
+      if (!fromIdentityObject.equals(other.getFromIdentityObject())) return false;
+      if (!toIdentityObject.equals(other.getToIdentityObject())) return false;
+      if (!type.equals(other.getType())) return false;
+      if (name == null)
+      {
+         if (other.getName() != null) return false;
+      }
+      else
+      {
+         if (!name.equals(other.getName())) return false;
+      }
+      
+      return true;
+   }
+   
+   @Override
+   public int hashCode()
+   {
+      int hash = (fromIdentityObject.hashCode() * 11) ^
+             (toIdentityObject.hashCode() * 17) ^
+             (type.hashCode() * 23);
+      
+      if (name != null) hash ^= (name.hashCode() * 29);
+      
+      return hash;
+   }
+}

Added: idm/trunk/picketlink-idm-jpa/src/main/java/org/picketlink/idm/impl/store/jpa/IdentityObjectRelationshipTypeImpl.java
===================================================================
--- idm/trunk/picketlink-idm-jpa/src/main/java/org/picketlink/idm/impl/store/jpa/IdentityObjectRelationshipTypeImpl.java	                        (rev 0)
+++ idm/trunk/picketlink-idm-jpa/src/main/java/org/picketlink/idm/impl/store/jpa/IdentityObjectRelationshipTypeImpl.java	2011-02-07 10:18:43 UTC (rev 740)
@@ -0,0 +1,46 @@
+package org.picketlink.idm.impl.store.jpa;
+
+
+import java.io.Serializable;
+
+import org.picketlink.idm.spi.model.IdentityObjectRelationshipType;
+
+/**
+ * Simple implementation of IdentityObjectRelationshipType
+ * 
+ * @author Shane Bryzak
+ */
+public class IdentityObjectRelationshipTypeImpl implements IdentityObjectRelationshipType, Serializable
+{
+   private static final long serialVersionUID = 6389479876202629001L;
+
+   private String name;
+   
+   public IdentityObjectRelationshipTypeImpl(String name)
+   {
+      if (name == null) throw new IllegalArgumentException("IdentityObjectRelationshipType.name cannot be null.");
+      
+      this.name = name;
+   }
+   
+   public String getName()
+   {
+      return name;
+   }
+   
+   @Override
+   public boolean equals(Object value)
+   {
+      if (!(value instanceof IdentityObjectRelationshipType)) return false;
+      IdentityObjectRelationshipType other = (IdentityObjectRelationshipType) value;
+      
+      return name.equals(other.getName());
+   }
+   
+   @Override
+   public int hashCode()
+   {
+      return name.hashCode();
+   }
+
+}

Added: idm/trunk/picketlink-idm-jpa/src/main/java/org/picketlink/idm/impl/store/jpa/IdentityObjectTypeImpl.java
===================================================================
--- idm/trunk/picketlink-idm-jpa/src/main/java/org/picketlink/idm/impl/store/jpa/IdentityObjectTypeImpl.java	                        (rev 0)
+++ idm/trunk/picketlink-idm-jpa/src/main/java/org/picketlink/idm/impl/store/jpa/IdentityObjectTypeImpl.java	2011-02-07 10:18:43 UTC (rev 740)
@@ -0,0 +1,42 @@
+package org.picketlink.idm.impl.store.jpa;
+
+import java.io.Serializable;
+
+import org.picketlink.idm.spi.model.IdentityObjectType;
+
+/**
+ * Simple implementation of IdentityObjectType
+ * 
+ * @author Shane Bryzak
+ */
+public class IdentityObjectTypeImpl implements IdentityObjectType, Serializable
+{
+   private static final long serialVersionUID = -4364461076493738717L;
+   
+   private String name;
+   
+   public IdentityObjectTypeImpl(String name)
+   {
+      if (name == null) throw new IllegalArgumentException("IdentityObjectType name cannot be null");      
+      this.name = name;
+   }
+   
+   public String getName()
+   {
+      return name;
+   }
+   
+   @Override
+   public boolean equals(Object value)
+   {
+      if (!(value instanceof IdentityObjectType)) return false;
+      IdentityObjectType other = (IdentityObjectType) value;
+      return name.equals(other.getName());
+   }
+   
+   @Override
+   public int hashCode()
+   {
+      return name.hashCode();
+   }
+}

Added: idm/trunk/picketlink-idm-jpa/src/main/java/org/picketlink/idm/impl/store/jpa/IdentityProperty.java
===================================================================
--- idm/trunk/picketlink-idm-jpa/src/main/java/org/picketlink/idm/impl/store/jpa/IdentityProperty.java	                        (rev 0)
+++ idm/trunk/picketlink-idm-jpa/src/main/java/org/picketlink/idm/impl/store/jpa/IdentityProperty.java	2011-02-07 10:18:43 UTC (rev 740)
@@ -0,0 +1,24 @@
+package org.picketlink.idm.impl.store.jpa;
+
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+/**
+ * 
+ * @author Shane Bryzak
+ */
+ at Target({METHOD,FIELD})
+ at Documented
+ at Retention(RUNTIME)
+ at Inherited
+public @interface IdentityProperty {
+   PropertyType value();
+   String attributeName() default "";
+}

Added: idm/trunk/picketlink-idm-jpa/src/main/java/org/picketlink/idm/impl/store/jpa/IdentitySessionProducer.java
===================================================================
--- idm/trunk/picketlink-idm-jpa/src/main/java/org/picketlink/idm/impl/store/jpa/IdentitySessionProducer.java	                        (rev 0)
+++ idm/trunk/picketlink-idm-jpa/src/main/java/org/picketlink/idm/impl/store/jpa/IdentitySessionProducer.java	2011-02-07 10:18:43 UTC (rev 740)
@@ -0,0 +1,161 @@
+package org.picketlink.idm.impl.store.jpa;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+//import javax.enterprise.context.ApplicationScoped;
+//import javax.enterprise.context.RequestScoped;
+//import javax.enterprise.inject.Instance;
+//import javax.enterprise.inject.Produces;
+//import javax.enterprise.inject.spi.Bean;
+//import javax.enterprise.inject.spi.BeanManager;
+//import javax.inject.Inject;
+//import javax.persistence.EntityManager;
+
+import org.picketlink.idm.api.IdentitySession;
+import org.picketlink.idm.api.IdentitySessionFactory;
+import org.picketlink.idm.api.event.EventListener;
+import org.picketlink.idm.common.exception.IdentityConfigurationException;
+import org.picketlink.idm.common.exception.IdentityException;
+import org.picketlink.idm.impl.configuration.IdentityConfigurationImpl;
+import org.picketlink.idm.impl.configuration.metadata.IdentityConfigurationMetaDataImpl;
+import org.picketlink.idm.impl.configuration.metadata.IdentityRepositoryConfigurationMetaDataImpl;
+import org.picketlink.idm.impl.configuration.metadata.IdentityStoreConfigurationMetaDataImpl;
+import org.picketlink.idm.impl.configuration.metadata.IdentityStoreMappingMetaDataImpl;
+import org.picketlink.idm.impl.configuration.metadata.RealmConfigurationMetaDataImpl;
+import org.picketlink.idm.impl.repository.WrapperIdentityStoreRepository;
+import org.picketlink.idm.spi.configuration.metadata.IdentityRepositoryConfigurationMetaData;
+import org.picketlink.idm.spi.configuration.metadata.IdentityStoreConfigurationMetaData;
+import org.picketlink.idm.spi.configuration.metadata.IdentityStoreMappingMetaData;
+import org.picketlink.idm.spi.configuration.metadata.RealmConfigurationMetaData;
+
+/**
+ * Produces IdentitySession instances for identity management-related operations
+ * 
+ * @author Shane Bryzak
+ */
+//@ApplicationScoped
+public class IdentitySessionProducer implements EventListener
+{
+   private IdentitySessionFactory factory;
+   
+   private String defaultRealm = "default";   
+   private String defaultAttributeStoreId;
+   private String defaultIdentityStoreId;
+      
+   //@Inject BeanManager manager;
+   
+   //@Inject
+   public void init() throws IdentityConfigurationException, IdentityException
+   {
+//      IdentityConfigurationMetaDataImpl metadata = new IdentityConfigurationMetaDataImpl();
+//
+//      // Create the identity store configuration
+//      List<IdentityStoreConfigurationMetaData> stores = new ArrayList<IdentityStoreConfigurationMetaData>();
+//
+//      String defaultStoreId = null;
+//
+//      Set<Bean<?>> storeBeans = manager.getBeans(IdentityStoreConfiguration.class);
+//      for (Bean<?> storeBean : storeBeans)
+//      {
+//         IdentityStoreConfiguration config = (IdentityStoreConfiguration) manager
+//            .getReference(storeBean, IdentityStoreConfiguration.class,
+//                  manager.createCreationalContext(storeBean));
+//
+//         IdentityStoreConfigurationMetaDataImpl store = new IdentityStoreConfigurationMetaDataImpl();
+//         config.configure(store);
+//
+//         if (defaultStoreId == null && store.getId() != null)
+//         {
+//            defaultStoreId = store.getId();
+//         }
+//
+//         stores.add(store);
+//      }
+//
+//      metadata.setIdentityStores(stores);
+//
+//      // Create the default realm
+//      RealmConfigurationMetaDataImpl realm = new RealmConfigurationMetaDataImpl();
+//      realm.setId(getDefaultRealm());
+//      realm.setIdentityMapping("USER");
+//      //realm.setGroupTypeMappings(groupTypeMappings)
+//      realm.setOptions(new HashMap<String,List<String>>());
+//      List<RealmConfigurationMetaData> realms = new ArrayList<RealmConfigurationMetaData>();
+//      realms.add(realm);
+//      metadata.setRealms(realms);
+//
+//      List<IdentityRepositoryConfigurationMetaData> repositories = new ArrayList<IdentityRepositoryConfigurationMetaData>();
+//
+//      IdentityRepositoryConfigurationMetaDataImpl repository = new IdentityRepositoryConfigurationMetaDataImpl();
+//      repository.setClassName(WrapperIdentityStoreRepository.class.getName());
+//      repository.setDefaultAttributeStoreId(defaultAttributeStoreId != null ? defaultAttributeStoreId : defaultStoreId);
+//      repository.setDefaultIdentityStoreId(defaultIdentityStoreId != null ? defaultIdentityStoreId : defaultStoreId);
+//
+//      List<IdentityStoreMappingMetaData> mappings = new ArrayList<IdentityStoreMappingMetaData>();
+//
+//      IdentityStoreMappingMetaDataImpl mapping = new IdentityStoreMappingMetaDataImpl();
+//      List<String> identityObjectTypes = new ArrayList<String>();
+//      identityObjectTypes.add("USER");
+//      identityObjectTypes.add("GROUP");
+//      mapping.setIdentityObjectTypeMappings(identityObjectTypes);
+//      mapping.setIdentityStoreId(defaultIdentityStoreId != null ? defaultIdentityStoreId : defaultStoreId);
+//      mappings.add(mapping);
+//
+//      repository.setIdentityStoreToIdentityObjectTypeMappings(mappings);
+//
+//      repositories.add(repository);
+//      metadata.setRepositories(repositories);
+//
+//      IdentityConfigurationImpl config = new IdentityConfigurationImpl();
+//      config.configure(metadata);
+//
+//      factory = config.buildIdentitySessionFactory();
+   }
+      
+   //@Inject Instance<EntityManager> entityManagerInstance;
+      
+//   @Produces @RequestScoped IdentitySession createIdentitySession()
+//      throws IdentityException
+//   {
+//      Map<String,Object> sessionOptions = new HashMap<String,Object>();
+//      sessionOptions.put("ENTITY_MANAGER", entityManagerInstance.get());
+//
+//      IdentitySession session = factory.createIdentitySession(getDefaultRealm(), sessionOptions);
+//      session.registerListener(this);
+//      return session;
+//   }
+
+   public String getDefaultRealm()
+   {
+      return defaultRealm;
+   }
+   
+   public void setDefaultRealm(String defaultRealm)
+   {
+      this.defaultRealm = defaultRealm;
+   }
+   
+   public String getDefaultAttributeStoreId()
+   {
+      return defaultAttributeStoreId;
+   }
+   
+   public void setDefaultAttributeStoreId(String defaultAttributeStoreId)
+   {
+      this.defaultAttributeStoreId = defaultAttributeStoreId;
+   }
+   
+   public String getDefaultIdentityStoreId()
+   {
+      return defaultIdentityStoreId;
+   }
+   
+   public void setDefaultIdentityStoreId(String defaultIdentityStoreId)
+   {
+      this.defaultIdentityStoreId = defaultIdentityStoreId;
+   }
+}

Added: idm/trunk/picketlink-idm-jpa/src/main/java/org/picketlink/idm/impl/store/jpa/IdentityStoreConfiguration.java
===================================================================
--- idm/trunk/picketlink-idm-jpa/src/main/java/org/picketlink/idm/impl/store/jpa/IdentityStoreConfiguration.java	                        (rev 0)
+++ idm/trunk/picketlink-idm-jpa/src/main/java/org/picketlink/idm/impl/store/jpa/IdentityStoreConfiguration.java	2011-02-07 10:18:43 UTC (rev 740)
@@ -0,0 +1,48 @@
+package org.picketlink.idm.impl.store.jpa;
+
+import org.picketlink.idm.impl.configuration.metadata.IdentityStoreConfigurationMetaDataImpl;
+
+/**
+ * Abstract bean for configuring identity stores
+ * 
+ * @author Shane Bryzak
+ */
+public abstract class IdentityStoreConfiguration
+{
+   private String id;
+   private Class<?> identityStoreClass;
+   
+   public String getId()
+   {
+      return id;
+   }
+   
+   public void setId(String id)
+   {
+      this.id = id;
+   }
+   
+   public Class<?> getIdentityStoreClass()
+   {
+      return identityStoreClass;
+   }
+   
+   public void setIdentityStoreClass(Class<?> identityStoreClass)
+   {
+      this.identityStoreClass = identityStoreClass;
+   }
+   
+   public void configure(IdentityStoreConfigurationMetaDataImpl store)
+   {
+      store.setId(getId());
+      
+      if (getIdentityStoreClass() != null)
+      {
+         store.setClassName(getIdentityStoreClass().getName());
+      }
+      
+      doConfigure(store);
+   }
+   
+   public abstract void doConfigure(IdentityStoreConfigurationMetaDataImpl store);
+}

Added: idm/trunk/picketlink-idm-jpa/src/main/java/org/picketlink/idm/impl/store/jpa/JpaIdentityStore.java
===================================================================
--- idm/trunk/picketlink-idm-jpa/src/main/java/org/picketlink/idm/impl/store/jpa/JpaIdentityStore.java	                        (rev 0)
+++ idm/trunk/picketlink-idm-jpa/src/main/java/org/picketlink/idm/impl/store/jpa/JpaIdentityStore.java	2011-02-07 10:18:43 UTC (rev 740)
@@ -0,0 +1,2090 @@
+package org.picketlink.idm.impl.store.jpa;
+
+import java.io.Serializable;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+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 javax.persistence.Entity;
+import javax.persistence.EntityManager;
+import javax.persistence.Id;
+import javax.persistence.NoResultException;
+import javax.persistence.criteria.CriteriaBuilder;
+import javax.persistence.criteria.CriteriaQuery;
+import javax.persistence.criteria.Predicate;
+import javax.persistence.criteria.Root;
+
+import org.jboss.seam.solder.properties.Property;
+import org.jboss.seam.solder.properties.query.AnnotatedPropertyCriteria;
+import org.jboss.seam.solder.properties.query.NamedPropertyCriteria;
+import org.jboss.seam.solder.properties.query.PropertyCriteria;
+import org.jboss.seam.solder.properties.query.PropertyQueries;
+import org.jboss.seam.solder.properties.query.TypedPropertyCriteria;
+import org.jboss.seam.solder.reflection.Reflections;
+import org.picketlink.idm.common.exception.IdentityException;
+import org.picketlink.idm.impl.api.SimpleAttribute;
+import org.picketlink.idm.impl.store.FeaturesMetaDataImpl;
+import org.picketlink.idm.spi.configuration.IdentityStoreConfigurationContext;
+import org.picketlink.idm.spi.configuration.metadata.IdentityObjectAttributeMetaData;
+import org.picketlink.idm.spi.exception.OperationNotSupportedException;
+import org.picketlink.idm.spi.model.IdentityObject;
+import org.picketlink.idm.spi.model.IdentityObjectAttribute;
+import org.picketlink.idm.spi.model.IdentityObjectCredential;
+import org.picketlink.idm.spi.model.IdentityObjectRelationship;
+import org.picketlink.idm.spi.model.IdentityObjectRelationshipType;
+import org.picketlink.idm.spi.model.IdentityObjectType;
+import org.picketlink.idm.spi.search.IdentityObjectSearchCriteria;
+import org.picketlink.idm.spi.store.FeaturesMetaData;
+import org.picketlink.idm.spi.store.IdentityObjectSearchCriteriaType;
+import org.picketlink.idm.spi.store.IdentityStore;
+import org.picketlink.idm.spi.store.IdentityStoreInvocationContext;
+import org.picketlink.idm.spi.store.IdentityStoreSession;
+
+/**
+ * IdentityStore implementation that allows identity related data to be 
+ * persisted in a database via JPA
+ *  
+ * @author Shane Bryzak
+ */
+public class JpaIdentityStore implements IdentityStore, Serializable
+{
+   private static final long serialVersionUID = 7729139146633529501L;
+   
+   public static final String OPTION_IDENTITY_CLASS_NAME = "identityEntityClassName";
+   public static final String OPTION_CREDENTIAL_CLASS_NAME = "credentialEntityClassName";
+   public static final String OPTION_RELATIONSHIP_CLASS_NAME = "relationshipEntityClassName";
+   public static final String OPTION_ROLE_TYPE_CLASS_NAME = "roleTypeEntityClassName";
+   
+   private static final String DEFAULT_USER_IDENTITY_TYPE = "USER";
+   private static final String DEFAULT_ROLE_IDENTITY_TYPE = "ROLE";
+   private static final String DEFAULT_GROUP_IDENTITY_TYPE = "GROUP";   
+   
+   private static final String DEFAULT_RELATIONSHIP_TYPE_MEMBERSHIP = "MEMBERSHIP";
+   private static final String DEFAULT_RELATIONSHIP_TYPE_ROLE = "ROLE";
+
+   // Property keys
+   
+   private static final String PROPERTY_IDENTITY_ID = "IDENTITY_ID";
+   private static final String PROPERTY_IDENTITY_NAME = "IDENTITY_NAME";
+   private static final String PROPERTY_IDENTITY_TYPE = "IDENTITY_TYPE";
+   private static final String PROPERTY_IDENTITY_TYPE_NAME = "IDENTITY_TYPE_NAME";
+   private static final String PROPERTY_CREDENTIAL_VALUE = "CREDENTIAL_VALUE";
+   private static final String PROPERTY_CREDENTIAL_TYPE = "CREDENTIAL_TYPE";
+   private static final String PROPERTY_CREDENTIAL_TYPE_NAME = "CREDENTIAL_TYPE_NAME";
+   private static final String PROPERTY_CREDENTIAL_IDENTITY = "CREDENTIAL_IDENTITY";
+   private static final String PROPERTY_RELATIONSHIP_FROM = "RELATIONSHIP_FROM";
+   private static final String PROPERTY_RELATIONSHIP_TO = "RELATIONSHIP_TO";
+   private static final String PROPERTY_RELATIONSHIP_TYPE = "RELATIONSHIP_TYPE";
+   private static final String PROPERTY_RELATIONSHIP_TYPE_NAME = "RELATIONSHIP_TYPE_NAME";
+   private static final String PROPERTY_RELATIONSHIP_NAME = "RELATIONSHIP_NAME";
+
+   private static final String PROPERTY_ROLE_TYPE_NAME = "RELATIONSHIP_NAME_NAME";
+   
+   private static final String PROPERTY_ATTRIBUTE_NAME = "ATTRIBUTE_NAME";
+   private static final String PROPERTY_ATTRIBUTE_VALUE = "ATTRIBUTE_VALUE";
+   private static final String PROPERTY_ATTRIBUTE_IDENTITY = "ATTRIBUTE_IDENTITY";  
+   
+   private class EntityToSpiConverter
+   {
+      private static final String IDENTITY_TYPE_CACHE_PREFIX = "identity_type:";
+      private static final String RELATIONSHIP_TYPE_CACHE_PREFIX = "relationship_type:";
+      
+      private Map<Object,Object> cache = new HashMap<Object,Object>();
+      
+      private Property<?> identityIdProperty = modelProperties.get(PROPERTY_IDENTITY_ID);
+      private Property<?> identityNameProperty = modelProperties.get(PROPERTY_IDENTITY_NAME);
+      private Property<?> identityTypeProperty = modelProperties.get(PROPERTY_IDENTITY_TYPE);
+      private Property<?> identityTypeNameProperty = modelProperties.get(PROPERTY_IDENTITY_TYPE_NAME);
+      private Property<?> relationshipTypeNameProperty = modelProperties.get(PROPERTY_RELATIONSHIP_TYPE_NAME);
+      
+      public IdentityObject convertToIdentityObject(Object entity)
+      {
+         if (!identityClass.isAssignableFrom(entity.getClass())) 
+         {
+            throw new IllegalArgumentException("Invalid identity entity");
+         }
+         
+         if (cache.containsKey(entity))
+         {
+            return (IdentityObject) cache.get(entity);
+         }
+         else
+         {         
+            IdentityObject obj = new IdentityObjectImpl(
+               identityIdProperty.getValue(entity).toString(),
+               identityNameProperty.getValue(entity).toString(),
+               convertToIdentityObjectType(identityTypeProperty.getValue(entity)));
+            cache.put(entity, obj);
+            
+            return obj;            
+         }
+      }
+      
+      public IdentityObjectType convertToIdentityObjectType(Object value)
+      {
+         if (value instanceof String)
+         {
+            String key = IDENTITY_TYPE_CACHE_PREFIX + (String) value; 
+            if (cache.containsKey(key)) return (IdentityObjectType) cache.get(key);
+            
+            IdentityObjectType type = new IdentityObjectTypeImpl((String) value);
+            cache.put(key, type);
+            return type;
+         }
+         else
+         {
+            if (cache.containsKey(value)) return (IdentityObjectType) cache.get(value);
+            IdentityObjectType type = new IdentityObjectTypeImpl(
+                  (String) identityTypeNameProperty.getValue(value));
+            cache.put(value, type);
+            return type;
+         }
+      }
+      
+      public IdentityObjectRelationshipType convertToRelationshipType(Object value)
+      {
+         if (value instanceof String)
+         {
+            String key = RELATIONSHIP_TYPE_CACHE_PREFIX + (String) value;
+            if (cache.containsKey(key)) return (IdentityObjectRelationshipType) cache.get(key);
+            
+            IdentityObjectRelationshipType type = new IdentityObjectRelationshipTypeImpl((String) value);
+            cache.put(key, type);
+            return type;
+         }
+         else
+         {
+            if (cache.containsKey(value)) return (IdentityObjectRelationshipType) cache.get(value);
+            IdentityObjectRelationshipType type = new IdentityObjectRelationshipTypeImpl(
+                  (String) relationshipTypeNameProperty.getValue(value));
+            cache.put(value, type);
+            return type;
+         }
+      }
+   }
+   
+   
+   private String id;
+      
+   // Entity classes   
+   private Class<?> identityClass;
+   private Class<?> credentialClass;
+   private Class<?> relationshipClass;   
+   private Class<?> attributeClass;
+   private Class<?> roleTypeClass;
+   
+   private String userIdentityType = DEFAULT_USER_IDENTITY_TYPE;
+   private String roleIdentityType = DEFAULT_ROLE_IDENTITY_TYPE;
+   private String groupIdentityType = DEFAULT_GROUP_IDENTITY_TYPE;
+   
+   private String relationshipTypeMembership = DEFAULT_RELATIONSHIP_TYPE_MEMBERSHIP;
+   private String relationshipTypeRole = DEFAULT_RELATIONSHIP_TYPE_ROLE;
+   
+   /**
+    * Model properties
+    */
+   private Map<String,Property<Object>> modelProperties = new HashMap<String,Property<Object>>();   
+   
+   /**
+    * Attribute properties
+    */
+   private Map<String,Property<Object>> attributeProperties = new HashMap<String,Property<Object>>();
+   
+   private FeaturesMetaData featuresMetaData;
+   
+   private class PropertyTypeCriteria implements PropertyCriteria
+   {
+      private PropertyType pt;
+      
+      public PropertyTypeCriteria(PropertyType pt)
+      {
+         this.pt = pt;
+      }
+      
+      public boolean fieldMatches(Field f)
+      {
+         return f.isAnnotationPresent(IdentityProperty.class) &&
+            f.getAnnotation(IdentityProperty.class).value().equals(pt);
+      }
+
+      public boolean methodMatches(Method m)
+      {
+         return m.isAnnotationPresent(IdentityProperty.class) &&
+            m.getAnnotation(IdentityProperty.class).value().equals(pt);
+      }      
+   }
+   
+   public JpaIdentityStore(String id)
+   {
+      this.id = id;
+   }
+   
+   public void bootstrap(IdentityStoreConfigurationContext configurationContext)
+      throws IdentityException
+   {           
+      String clsName = configurationContext.getStoreConfigurationMetaData()
+         .getOptionSingleValue(OPTION_IDENTITY_CLASS_NAME);
+
+      if (clsName == null)
+      {
+         throw new IdentityException("Error bootstrapping JpaIdentityStore - identity entity class cannot be null");
+      }
+      
+      try
+      {
+         identityClass = Reflections.classForName(clsName);
+      }
+      catch (ClassNotFoundException e)
+      {
+         throw new IdentityException("Error bootstrapping JpaIdentityStore - invalid identity entity class: " + clsName);
+      }
+      
+      if (identityClass == null)
+      {
+         throw new IdentityException(
+               "Error initializing JpaIdentityStore - identityClass not set");
+      }
+      
+      clsName = configurationContext.getStoreConfigurationMetaData()
+         .getOptionSingleValue(OPTION_CREDENTIAL_CLASS_NAME);
+      
+      if (clsName != null)
+      {
+         try
+         {
+            credentialClass = Class.forName(clsName);
+         }
+         catch (ClassNotFoundException e)
+         {
+            throw new IdentityException("Error bootstrapping JpaIdentityStore - invalid credential entity class: " + clsName);
+         }
+      }
+      
+      clsName = configurationContext.getStoreConfigurationMetaData()
+         .getOptionSingleValue(OPTION_RELATIONSHIP_CLASS_NAME);
+      
+      try
+      {
+         relationshipClass = Class.forName(clsName);
+      }
+      catch (ClassNotFoundException e)
+      {
+         throw new IdentityException("Error bootstrapping JpaIdentityStore - invalid relationship entity class: " + clsName);
+      }      
+      
+      boolean namedRelationshipsSupported = false;
+      
+      clsName = configurationContext.getStoreConfigurationMetaData()
+         .getOptionSingleValue(OPTION_ROLE_TYPE_CLASS_NAME);
+      
+      if (clsName != null)
+      {
+         try
+         {
+            roleTypeClass = Class.forName(clsName);
+            namedRelationshipsSupported = true;
+         }
+         catch (ClassNotFoundException e)
+         {
+            throw new IdentityException("Error bootstrapping JpaIdentityStore - invalid role type entity class: " + clsName);
+         }
+      }
+      
+      configureIdentityId();
+      configureIdentityName();
+      configureIdentityType();
+      
+      configureCredentials();
+      configureRelationships();
+      configureAttributes();   
+      
+      if (namedRelationshipsSupported)
+      {
+         configureRoleTypeName();
+      }
+      
+      featuresMetaData = new FeaturesMetaDataImpl(
+            configurationContext.getStoreConfigurationMetaData(),
+            new HashSet<IdentityObjectSearchCriteriaType>(),
+            false,
+            namedRelationshipsSupported,
+            new HashSet<String>()
+            );            
+   }   
+   
+   protected void configureIdentityId() throws IdentityException
+   {
+      List<Property<Object>> props = PropertyQueries.createQuery(identityClass)
+         .addCriteria(new AnnotatedPropertyCriteria(Id.class))
+         .getResultList();
+      
+      if (props.size() == 1)
+      {
+         modelProperties.put(PROPERTY_IDENTITY_ID, props.get(0));
+      }
+      else
+      {
+         throw new IdentityException("Error initializing JpaIdentityStore - no Identity ID found.");
+      }
+   }
+      
+   protected void configureIdentityName() throws IdentityException
+   {      
+      List<Property<Object>> props = PropertyQueries.createQuery(identityClass)
+         .addCriteria(new PropertyTypeCriteria(PropertyType.NAME))
+         .getResultList();
+      
+      if (props.size() == 1)
+      {
+         modelProperties.put(PROPERTY_IDENTITY_NAME, props.get(0));
+      }
+      else if (props.size() > 1)
+      {
+         throw new IdentityException(
+               "Ambiguous identity name property in identity class " + identityClass.getName());
+      }
+      else
+      {
+         Property<Object> p = findNamedProperty(identityClass, "username", "userName", "name");
+         if (p != null) 
+         {
+            modelProperties.put(PROPERTY_IDENTITY_NAME, p);
+         }
+         else 
+         {
+            // Last resort - check whether the entity class exposes a single String property
+            // if so, let's assume it's the identity name
+            props = PropertyQueries.createQuery(identityClass)
+               .addCriteria(new TypedPropertyCriteria(String.class))
+               .getResultList();
+            if (props.size() == 1)
+            {
+               modelProperties.put(PROPERTY_IDENTITY_NAME, props.get(0));
+            }
+         }
+      }
+
+      if (!modelProperties.containsKey(PROPERTY_IDENTITY_NAME))
+      {
+         throw new IdentityException("Error initializing JpaIdentityStore - no valid identity name property found.");
+      }
+   }
+   
+   protected void configureIdentityType() throws IdentityException
+   {      
+      List<Property<Object>> props = PropertyQueries.createQuery(identityClass)
+         .addCriteria(new PropertyTypeCriteria(PropertyType.TYPE))
+         .getResultList();
+      
+      if (props.size() == 1)
+      {
+         modelProperties.put(PROPERTY_IDENTITY_TYPE, props.get(0));
+      }
+      else if (props.size() > 1)
+      {
+         throw new IdentityException(
+               "Ambiguous identity type property in identity class " + identityClass.getName());
+      }
+      else
+      {
+         Property<Object> p = findNamedProperty(identityClass, "identityObjectType", 
+               "identityType", "identityObjectTypeName", "identityTypeName", 
+               "typeName", "discriminator", "accountType", "userType", "type");
+         if (p != null) 
+         {
+            modelProperties.put(PROPERTY_IDENTITY_TYPE, props.get(0));
+         }
+         else 
+         {
+            // Last resort - let's check all properties, and try to find one
+            // with an entity type that has "type" in its name
+            props = PropertyQueries.createQuery(identityClass).getResultList();
+            search: for (Property<Object> typeProp : props)
+            {
+               if (typeProp.getJavaClass().isAnnotationPresent(Entity.class) && 
+                     (typeProp.getJavaClass().getSimpleName().contains("type") ||
+                           typeProp.getJavaClass().getSimpleName().contains("Type")))
+               {
+                  // we have a potential match, let's check if this entity has a name property
+                  Property<Object> nameProp = findNamedProperty(typeProp.getJavaClass(),
+                        "identityObjectTypeName", "identityTypeName", "typeName", "name");
+                  if (nameProp != null)
+                  {
+                     modelProperties.put(PROPERTY_IDENTITY_TYPE, typeProp);
+                     modelProperties.put(PROPERTY_IDENTITY_TYPE_NAME, nameProp);
+                     break search;
+                  }
+               }
+            }
+         }         
+      }      
+      
+      Property<?> typeProp = modelProperties.get(PROPERTY_IDENTITY_TYPE);
+      
+      if (typeProp == null)
+      {
+         throw new IdentityException("Error initializing JpaIdentityStore - no valid identity type property found.");
+      }
+      
+      if (!String.class.equals(typeProp.getJavaClass()) && 
+            !modelProperties.containsKey(PROPERTY_IDENTITY_TYPE_NAME))
+      {
+         // We're not dealing with a simple type name - validate the lookup type
+         Property<Object> nameProp = findNamedProperty(typeProp.getJavaClass(),
+               "identityObjectTypeName", "identityTypeName", "typeName", "name");
+         if (nameProp != null)
+         {
+            modelProperties.put(PROPERTY_IDENTITY_TYPE_NAME, nameProp);
+         }
+         else
+         {
+            throw new IdentityException("Error initializing JpaIdentityStore - no valid identity type name property found.");
+         }
+      }
+   }
+   
+   protected Property<Object> findNamedProperty(Class<?> targetClass, String... allowedNames)
+   {
+      List<Property<Object>> props = PropertyQueries.createQuery(targetClass)
+         .addCriteria(new TypedPropertyCriteria(String.class))
+         .addCriteria(new PropertyTypeCriteria(PropertyType.NAME))
+         .getResultList();
+      
+      if (props.size() == 1)
+      {
+         return props.get(0);
+      }
+      else
+      {
+         props = PropertyQueries.createQuery(targetClass)
+            .addCriteria(new TypedPropertyCriteria(String.class))
+            .addCriteria(new NamedPropertyCriteria(allowedNames))
+            .getResultList();
+         
+         for (String name : allowedNames)
+         {
+            for (Property<Object> prop : props)
+            {
+               if (name.equals(prop.getName())) return prop;
+            }
+         }
+      }      
+      
+      return null;
+   }
+   
+   protected void configureCredentials() throws IdentityException
+   {
+      // If a credential entity has been explicitly configured, scan it
+      if (credentialClass != null)
+      {
+         List<Property<Object>> props = PropertyQueries.createQuery(credentialClass)
+            .addCriteria(new PropertyTypeCriteria(PropertyType.VALUE))
+            .getResultList();
+         
+         if (props.size() == 1)
+         {
+            modelProperties.put(PROPERTY_CREDENTIAL_VALUE, props.get(0));
+         }
+         else if (props.size() > 1)
+         {
+            throw new IdentityException(
+                  "Ambiguous credential value property in credential class " + 
+                  credentialClass.getName());
+         }
+         else
+         {
+            // Try scanning for a credential property also
+            props = PropertyQueries.createQuery(credentialClass)
+               .addCriteria(new PropertyTypeCriteria(PropertyType.CREDENTIAL))
+               .getResultList();
+            if (props.size() == 1)
+            {
+               modelProperties.put(PROPERTY_CREDENTIAL_VALUE, props.get(0));
+            }
+            else if (props.size() > 1)
+            {
+               throw new IdentityException(
+                     "Ambiguous credential value property in credential class " + 
+                     credentialClass.getName());
+            }
+            else
+            {
+               Property<Object> p = findNamedProperty(credentialClass, "credentialValue", 
+                     "password", "passwordHash", "credential", "value");
+               if (p != null) modelProperties.put(PROPERTY_CREDENTIAL_VALUE, p);
+            }
+         }  
+         
+         // Scan for the credential identity property
+         props = PropertyQueries.createQuery(credentialClass)
+            .addCriteria(new TypedPropertyCriteria(identityClass))
+            .getResultList();
+         if (props.size() == 1)
+         {
+            modelProperties.put(PROPERTY_CREDENTIAL_IDENTITY, props.get(0));
+         }
+         else if (props.size() > 1)
+         {
+            throw new IdentityException(
+                  "Ambiguous identity property in credential class " + 
+                  credentialClass.getName());
+         }
+         else
+         {
+            // Scan for a named identity property
+            props = PropertyQueries.createQuery(credentialClass)
+               .addCriteria(new NamedPropertyCriteria("identity", "identityObject"))
+               .getResultList();
+            if (!props.isEmpty())
+            {
+               modelProperties.put(PROPERTY_CREDENTIAL_IDENTITY, props.get(0));
+            }
+            else
+            {
+               throw new IdentityException("Error initializing JpaIdentityStore - no credential identity property found.");
+            }
+         }
+      }
+      else
+      {
+         // The credentials may be stored in the identity class         
+         List<Property<Object>> props = PropertyQueries.createQuery(identityClass)
+            .addCriteria(new PropertyTypeCriteria(PropertyType.CREDENTIAL))
+            .getResultList();
+         
+         if (props.size() == 1)
+         {
+            modelProperties.put(PROPERTY_CREDENTIAL_VALUE, props.get(0));
+         }
+         else if (props.size() > 1)
+         {
+            throw new IdentityException(
+                  "Ambiguous credential property in identity class " +
+                  identityClass.getName());
+         }
+         else
+         {         
+            Property<Object> p = findNamedProperty(identityClass, "credentialValue", 
+                  "password", "passwordHash", "credential", "value");
+            if (p != null) modelProperties.put(PROPERTY_CREDENTIAL_VALUE, p);
+         }
+      }
+            
+      if (!modelProperties.containsKey(PROPERTY_CREDENTIAL_VALUE))
+      {
+         throw new IdentityException("Error initializing JpaIdentityStore - no credential value property found.");
+      }            
+            
+      // Scan for a credential type property
+      List<Property<Object>> props = PropertyQueries.createQuery(credentialClass)
+         .addCriteria(new PropertyTypeCriteria(PropertyType.TYPE))
+         .getResultList();
+      
+      if (props.size() == 1)
+      {
+         modelProperties.put(PROPERTY_CREDENTIAL_TYPE, props.get(0));
+      }
+      else if (props.size() > 1)
+      {
+         throw new IdentityException(
+               "Ambiguous credential type property in credential class " + 
+               credentialClass.getName());
+      }
+      else
+      {
+         props = PropertyQueries.createQuery(credentialClass)
+            .addCriteria(new PropertyTypeCriteria(PropertyType.CREDENTIAL_TYPE))
+            .getResultList();
+         
+         if (props.size() == 1)
+         {
+            modelProperties.put(PROPERTY_CREDENTIAL_TYPE, props.get(0));
+         }
+         else if (props.size() > 1)
+         {
+            throw new IdentityException(
+                  "Ambiguous credential type property in credential class " + 
+                  credentialClass.getName());            
+         }
+         else
+         {         
+            Property<Object> p = findNamedProperty(credentialClass, "credentialType", 
+                  "identityObjectCredentialType", "type");
+            if (p != null) modelProperties.put(PROPERTY_CREDENTIAL_TYPE, p);
+         }
+      }      
+
+      Property<?> typeProp = modelProperties.get(PROPERTY_CREDENTIAL_TYPE);      
+      
+      // If the credential type property isn't a String, then validate the lookup type
+      if (!String.class.equals(typeProp.getJavaClass()))
+      {
+         Property<Object> nameProp = findNamedProperty(typeProp.getJavaClass(),
+               "credentialObjectTypeName", "credentialTypeName", "typeName", "name");
+         if (nameProp != null)
+         {
+            modelProperties.put(PROPERTY_CREDENTIAL_TYPE_NAME, nameProp);
+         }
+         else
+         {
+            throw new IdentityException("Error initializing JpaIdentityStore - no valid credential type name property found.");
+         }
+      }       
+   }
+   
+   protected void configureRelationships() throws IdentityException
+   {
+      if (relationshipClass == null)
+      {
+         throw new IdentityException("Error initializing JpaIdentityStore - relationshipClass not set.");
+      }
+      
+      List<Property<Object>> props = PropertyQueries.createQuery(relationshipClass)
+         .addCriteria(new TypedPropertyCriteria(identityClass))
+         .addCriteria(new PropertyTypeCriteria(PropertyType.RELATIONSHIP_FROM))
+         .getResultList();
+      
+      if (props.size() == 1)
+      {
+         modelProperties.put(PROPERTY_RELATIONSHIP_FROM, props.get(0));
+      }
+      else if (props.size() > 1)
+      {
+         throw new IdentityException(
+               "Ambiguous relationshipFrom property in relationship class " + 
+               relationshipClass.getName());
+      }
+      else
+      {
+         Property<Object> p = findNamedProperty(relationshipClass, "relationshipFrom", 
+               "fromIdentityObject", "fromIdentity");
+         if (p != null) 
+         {
+            modelProperties.put(PROPERTY_RELATIONSHIP_FROM, p);
+         }
+         else
+         {
+            // Last resort - search for a property with a type of identityClass
+            // and a "from" in its name
+            props = PropertyQueries.createQuery(relationshipClass)
+               .addCriteria(new TypedPropertyCriteria(identityClass))
+               .getResultList();
+            
+            for (Property<Object> prop : props)
+            {
+               if (prop.getName().contains("from"))
+               {
+                  modelProperties.put(PROPERTY_RELATIONSHIP_FROM, prop);
+                  break;
+               }
+            }
+         }         
+      }
+  
+      
+      props = PropertyQueries.createQuery(relationshipClass)
+         .addCriteria(new TypedPropertyCriteria(identityClass))
+         .addCriteria(new PropertyTypeCriteria(PropertyType.RELATIONSHIP_TO))
+         .getResultList();
+   
+      if (props.size() == 1)
+      {
+         modelProperties.put(PROPERTY_RELATIONSHIP_TO, props.get(0));
+      }
+      else if (props.size() > 1)
+      {
+         throw new IdentityException(
+               "Ambiguous relationshipTo property in relationship class " + 
+               relationshipClass.getName());
+      }
+      else
+      {
+         Property<Object> p = findNamedProperty(relationshipClass, "relationshipTo", 
+               "toIdentityObject", "toIdentity");
+         if (p != null) 
+         {
+            modelProperties.put(PROPERTY_RELATIONSHIP_TO, p);
+         }
+         else
+         {
+            // Last resort - search for a property with a type of identityClass
+            // and a "to" in its name
+            props = PropertyQueries.createQuery(relationshipClass)
+               .addCriteria(new TypedPropertyCriteria(identityClass))
+               .getResultList();
+            
+            for (Property<Object> prop : props)
+            {
+               if (prop.getName().contains("to"))
+               {
+                  modelProperties.put(PROPERTY_RELATIONSHIP_TO, prop);
+                  break;
+               }
+            }
+         }         
+      }      
+      
+      props = PropertyQueries.createQuery(relationshipClass)
+         .addCriteria(new PropertyTypeCriteria(PropertyType.TYPE))
+         .getResultList();
+      if (props.size() == 1)
+      {
+         modelProperties.put(PROPERTY_RELATIONSHIP_TYPE, props.get(0));
+      }
+      else if (props.size() > 1)
+      {
+         throw new IdentityException(
+               "Ambiguous relationshipType property in relationship class " +
+               relationshipClass.getName());
+      }
+      else
+      {
+         Property<Object> p = findNamedProperty(relationshipClass, 
+               "identityRelationshipType", "relationshipType", "type");
+         if (p != null)
+         {
+            modelProperties.put(PROPERTY_RELATIONSHIP_TYPE, p);
+         }
+         else
+         {
+            props = PropertyQueries.createQuery(relationshipClass)
+               .getResultList();
+            for (Property<Object> prop : props)
+            {
+               if (prop.getName().contains("type"))
+               {
+                  modelProperties.put(PROPERTY_RELATIONSHIP_TYPE, prop);
+                  break;
+               }
+            }
+         }
+      }
+      
+      props = PropertyQueries.createQuery(relationshipClass)
+         .addCriteria(new PropertyTypeCriteria(PropertyType.NAME))
+         .addCriteria(new TypedPropertyCriteria(String.class))
+         .getResultList();
+      
+      if (props.size() == 1)
+      {
+         modelProperties.put(PROPERTY_RELATIONSHIP_NAME, props.get(0));
+      }
+      else if (props.size() > 1)
+      {
+         throw new IdentityException(
+               "Ambiguous relationship name property in relationship class " +
+               relationshipClass.getName());
+      }
+      else
+      {
+         Property<Object> p = findNamedProperty(relationshipClass,
+               "relationshipName", "name");
+         if (p != null)
+         {
+            modelProperties.put(PROPERTY_RELATIONSHIP_NAME, p);
+         }
+      }
+      
+      if (!modelProperties.containsKey(PROPERTY_RELATIONSHIP_FROM))
+      {
+         throw new IdentityException(
+            "Error initializing JpaIdentityStore - no valid relationship from property found.");
+      }
+      
+      if (!modelProperties.containsKey(PROPERTY_RELATIONSHIP_TO))
+      {
+         throw new IdentityException(
+            "Error initializing JpaIdentityStore - no valid relationship to property found.");
+      }
+      
+      if (!modelProperties.containsKey(PROPERTY_RELATIONSHIP_TYPE))
+      {
+         throw new IdentityException(
+            "Error initializing JpaIdentityStore - no valid relationship type property found.");
+      }
+      
+      if (!modelProperties.containsKey(PROPERTY_RELATIONSHIP_NAME))
+      {
+         throw new IdentityException(
+            "Error initializing JpaIdentityStore - no valid relationship name property found.");
+      }
+      
+      Class<?> typeClass = modelProperties.get(PROPERTY_RELATIONSHIP_TYPE).getJavaClass();
+      if (!String.class.equals(typeClass))
+      {
+         props = PropertyQueries.createQuery(typeClass)
+            .addCriteria(new PropertyTypeCriteria(PropertyType.NAME))
+            .addCriteria(new TypedPropertyCriteria(String.class))
+            .getResultList();
+         
+         if (props.size() == 1)
+         {
+            modelProperties.put(PROPERTY_RELATIONSHIP_TYPE_NAME, props.get(0));
+         }
+         else if (props.size() > 1)
+         {
+            throw new IdentityException(
+                  "Ambiguous relationship type name property in class " +
+                  typeClass.getName());
+         }
+         else
+         {
+            Property<Object> p = findNamedProperty(typeClass, "relationshipTypeName",
+                  "typeName", "name");
+            if (p != null)
+            {
+               modelProperties.put(PROPERTY_RELATIONSHIP_TYPE_NAME, p);
+            }
+         }
+         
+         if (!modelProperties.containsKey(PROPERTY_RELATIONSHIP_TYPE_NAME))
+         {
+            throw new IdentityException(
+                  "Error initializing JpaIdentityStore - no valid relationship type name property found");
+         }
+      }      
+   }
+   
+   protected void configureAttributes() throws IdentityException
+   {
+      // If an attribute class has been configured, scan it for attributes
+      if (attributeClass != null)
+      {
+         List<Property<Object>> props = PropertyQueries.createQuery(attributeClass)
+            .addCriteria(new PropertyTypeCriteria(PropertyType.NAME))
+            .addCriteria(new TypedPropertyCriteria(String.class))
+            .getResultList();
+         
+         if (props.size() == 1)
+         {
+            modelProperties.put(PROPERTY_ATTRIBUTE_NAME, props.get(0));
+         }
+         else if (props.size() > 1)
+         {
+            throw new IdentityException(
+            		"Ambiguous attribute name property in class " +
+            		attributeClass.getName());
+         }
+         else
+         {
+            Property<Object> prop = findNamedProperty(attributeClass,
+                  "attributeName", "name");
+            if (prop != null) modelProperties.put(PROPERTY_ATTRIBUTE_NAME, prop);
+         }
+         
+         props = PropertyQueries.createQuery(attributeClass)
+            .addCriteria(new PropertyTypeCriteria(PropertyType.VALUE))
+            .getResultList();
+         
+         if (props.size() == 1)
+         {
+            modelProperties.put(PROPERTY_ATTRIBUTE_VALUE, props.get(0));
+         }
+         else if (props.size() > 1)
+         {
+            throw new IdentityException(
+                  "Ambiguous attribute value property in class " +
+                  attributeClass.getName());
+         }
+         else
+         {
+            Property<Object> prop = findNamedProperty(attributeClass, 
+                  "attributeValue", "value");
+            if (prop != null) modelProperties.put(PROPERTY_ATTRIBUTE_VALUE, prop);
+         }
+         
+         props = PropertyQueries.createQuery(attributeClass)
+            .addCriteria(new TypedPropertyCriteria(identityClass))
+            .getResultList();
+         
+         if (props.size() == 1)
+         {
+            modelProperties.put(PROPERTY_ATTRIBUTE_IDENTITY, props.get(0));
+         }
+         else if (props.size() > 1)
+         {
+            throw new IdentityException(
+                  "Ambiguous identity property in attribute class " +
+                  attributeClass.getName());
+         }
+         else
+         {
+            throw new IdentityException("Error initializing JpaIdentityStore - " +
+                  "no attribute identity property found.");
+         }
+      }
+
+      // Scan for additional attributes in the identity class also
+      List<Property<Object>> props = PropertyQueries.createQuery(identityClass)
+         .addCriteria(new PropertyTypeCriteria(PropertyType.ATTRIBUTE))
+         .getResultList();
+   
+      for (Property<Object> p : props)
+      {
+         attributeProperties.put(
+               p.getAnnotatedElement().getAnnotation(IdentityProperty.class).attributeName(), 
+               p);
+      }
+      
+      // scan any entity classes referenced by the identity class also
+      props = PropertyQueries.createQuery(identityClass)
+         .getResultList();
+      
+      for (Property<Object> p : props)
+      {
+         if (!p.isReadOnly() && p.getJavaClass().isAnnotationPresent(Entity.class))
+         {
+            List<Property<Object>> pp = PropertyQueries.createQuery(p.getJavaClass())
+               .addCriteria(new PropertyTypeCriteria(PropertyType.ATTRIBUTE))
+               .getResultList();
+            
+            for (Property<Object> attributeProperty : pp)
+            {
+               attributeProperties.put(
+                     attributeProperty.getAnnotatedElement().getAnnotation(IdentityProperty.class).attributeName(), 
+                     attributeProperty);                        
+            }
+         }
+      }
+   }
+   
+   protected void configureRoleTypeName()
+   {
+      Property<Object> relationshipNameProp = findNamedProperty(roleTypeClass, "name");
+      if (relationshipNameProp != null)
+      {         
+         modelProperties.put(PROPERTY_ROLE_TYPE_NAME, relationshipNameProp);
+      }
+   }
+   
+   public String getUserIdentityType()
+   {
+      return userIdentityType;
+   }
+   
+   public void setUserIdentityType(String userIdentityType)
+   {
+      this.userIdentityType = userIdentityType;
+   }
+   
+   public String getRoleIdentityType()
+   {
+      return roleIdentityType;
+   }
+   
+   public void setRoleIdentityType(String roleIdentityType)
+   {
+      this.roleIdentityType = roleIdentityType;
+   }
+   
+   public String getGroupIdentityType()
+   {
+      return groupIdentityType;
+   }
+   
+   public void setGroupIdentityType(String groupIdentityType)
+   {
+      this.groupIdentityType = groupIdentityType;
+   }
+   
+   public String getRelationshipTypeMembership()
+   {
+      return relationshipTypeMembership;
+   }
+   
+   public void setRelationshipTypeMembership(String relationshipTypeMembership)
+   {
+      this.relationshipTypeMembership = relationshipTypeMembership;
+   }
+   
+   public String getRelationshipTypeRole()
+   {
+      return relationshipTypeRole;
+   }
+   
+   public void setRelationshipTypeRole(String relationshipTypeRole)
+   {
+      this.relationshipTypeRole = relationshipTypeRole;
+   }  
+   
+   public IdentityStoreSession createIdentityStoreSession(
+         Map<String, Object> sessionOptions) throws IdentityException
+   {
+      EntityManager em = (EntityManager) sessionOptions.get("ENTITY_MANAGER");
+      
+      return new JpaIdentityStoreSessionImpl(em);
+   }
+
+   public IdentityObject createIdentityObject(
+         IdentityStoreInvocationContext invocationCtx, String name,
+         IdentityObjectType identityObjectType) throws IdentityException
+   {
+      return createIdentityObject(invocationCtx, name, identityObjectType, null);
+   }
+   
+   protected Object lookupIdentityType(String identityType, EntityManager em)
+   {      
+      try
+      {
+         Property<Object> typeNameProp = modelProperties.get(PROPERTY_IDENTITY_TYPE_NAME);
+         
+         // If there is no identity type table, just return the name
+         if (typeNameProp == null) return identityType;
+         
+         Object val = em.createQuery(
+               "select t from " + typeNameProp.getDeclaringClass().getName() + 
+               " t where t." + typeNameProp.getName() +
+                " = :identityType")
+               .setParameter("identityType", identityType)
+               .getSingleResult();
+         return val;
+      }
+      catch (NoResultException ex)
+      {
+         return null;
+      }      
+   }
+
+   public IdentityObject createIdentityObject(
+         IdentityStoreInvocationContext ctx, String name,
+         IdentityObjectType identityObjectType, Map<String, String[]> attributes)
+         throws IdentityException
+   {
+      try
+      {
+         Object identityInstance = identityClass.newInstance();
+         modelProperties.get(PROPERTY_IDENTITY_NAME).setValue(identityInstance, name);
+         
+         Property<Object> typeProp = modelProperties.get(PROPERTY_IDENTITY_TYPE); 
+         
+         if (String.class.equals(typeProp.getJavaClass()))
+         {
+            typeProp.setValue(identityInstance, identityObjectType.getName());
+         }
+         else
+         {
+            typeProp.setValue(identityInstance, lookupIdentityType(identityObjectType.getName(), 
+                  getEntityManager(ctx)));
+         }
+               
+         //beanManager.fireEvent(new PrePersistUserEvent(identityInstance));
+         
+         EntityManager em = getEntityManager(ctx);
+         
+         em.persist(identityInstance);
+         
+         //beanManager.fireEvent(new UserCreatedEvent(identityInstance));
+         
+         // TODO persist attributes
+
+         Object id = modelProperties.get(PROPERTY_IDENTITY_ID).getValue(identityInstance);
+         IdentityObject obj = new IdentityObjectImpl(
+               (id != null ? id.toString() : null),
+               name, identityObjectType);
+
+         return obj;
+      }
+      catch (Exception ex)
+      {
+         throw new IdentityException("Error creating identity object", ex);
+      }    
+   }
+
+   public IdentityObjectRelationship createRelationship(
+         IdentityStoreInvocationContext invocationCtx,
+         IdentityObject fromIdentity, IdentityObject toIdentity,
+         IdentityObjectRelationshipType relationshipType,
+         String relationshipName, boolean createNames) throws IdentityException
+   {
+      try
+      {
+         EntityManager em = getEntityManager(invocationCtx);
+         
+         Object relationship = relationshipClass.newInstance();
+         
+         modelProperties.get(PROPERTY_RELATIONSHIP_FROM).setValue(relationship, 
+               lookupIdentity(fromIdentity, em));
+         modelProperties.get(PROPERTY_RELATIONSHIP_TO).setValue(relationship,
+               lookupIdentity(toIdentity, em));
+         
+         Property<Object> type = modelProperties.get(PROPERTY_RELATIONSHIP_TYPE);
+         if (String.class.equals(modelProperties.get(PROPERTY_RELATIONSHIP_TYPE).getJavaClass()))
+         {
+            type.setValue(relationship, relationshipType.getName());
+         }
+         else
+         {
+            type.setValue(relationship, lookupRelationshipType(relationshipType, em));
+         }
+         
+         modelProperties.get(PROPERTY_RELATIONSHIP_NAME).setValue(relationship, 
+               relationshipName);
+         
+         em.persist(relationship);
+         
+         return new IdentityObjectRelationshipImpl(fromIdentity, toIdentity,
+               relationshipName, relationshipType);
+      }
+      catch (Exception ex)
+      {
+         throw new IdentityException("Exception creating relationship", ex);
+      }
+   }
+   
+   protected Object lookupIdentity(IdentityObject obj, EntityManager em)
+   {
+      Property<?> identityNameProp = modelProperties.get(PROPERTY_IDENTITY_NAME);
+      Property<?> identityTypeProp = modelProperties.get(PROPERTY_IDENTITY_TYPE);
+      
+      CriteriaBuilder builder = em.getCriteriaBuilder();
+      CriteriaQuery<?> criteria = builder.createQuery(identityClass);
+      Root<?> root = criteria.from(identityClass);
+      
+      List<Predicate> predicates = new ArrayList<Predicate>();
+      predicates.add(builder.equal(root.get(identityNameProp.getName()), obj.getName()));
+      predicates.add(builder.equal(root.get(identityTypeProp.getName()), lookupIdentityType(obj.getIdentityType().getName(), em)));
+      
+      // TODO add criteria for identity type
+      
+      criteria.where(predicates.toArray(new Predicate[0]));
+      
+      return em.createQuery(criteria).getSingleResult();
+   }
+   
+   protected Object lookupCredentialTypeEntity(String name, EntityManager em)
+   {
+      Property<?> credentialTypeNameProp = modelProperties.get(PROPERTY_CREDENTIAL_TYPE_NAME);
+      
+      CriteriaBuilder builder = em.getCriteriaBuilder();
+      CriteriaQuery<?> criteria = builder.createQuery(credentialTypeNameProp.getDeclaringClass());
+      Root<?> root = criteria.from(credentialTypeNameProp.getDeclaringClass());
+      
+      List<Predicate> predicates = new ArrayList<Predicate>();
+      predicates.add(builder.equal(root.get(credentialTypeNameProp.getName()), name));      
+      criteria.where(predicates.toArray(new Predicate[0]));
+
+      return em.createQuery(criteria).getSingleResult();
+   }
+   
+   protected Object lookupRelationshipType(IdentityObjectRelationshipType relationshipType, EntityManager em)
+   {
+      Property<?> relationshipTypeNameProp = modelProperties.get(PROPERTY_RELATIONSHIP_TYPE_NAME);      
+      
+      if (relationshipTypeNameProp != null)
+      {
+         CriteriaBuilder builder = em.getCriteriaBuilder();
+         CriteriaQuery<?> criteria = builder.createQuery(relationshipTypeNameProp.getDeclaringClass());
+         Root<?> root = criteria.from(relationshipTypeNameProp.getDeclaringClass());
+         
+         List<Predicate> predicates = new ArrayList<Predicate>();
+         predicates.add(builder.equal(root.get(relationshipTypeNameProp.getName()), relationshipType.getName()));      
+         criteria.where(predicates.toArray(new Predicate[0]));
+
+         return em.createQuery(criteria).getSingleResult();
+      }
+      else
+      {
+         return relationshipType.getName();
+      }
+   }
+
+   public String createRelationshipName(IdentityStoreInvocationContext ctx,
+         String name) throws IdentityException, OperationNotSupportedException
+   {
+      try
+      {
+         Property<Object> roleTypeNameProp = modelProperties.get(PROPERTY_ROLE_TYPE_NAME);
+         
+         Object roleTypeInstance = roleTypeClass.newInstance();
+         roleTypeNameProp.setValue(roleTypeInstance, name);
+         
+         EntityManager em = getEntityManager(ctx);
+         
+         em.persist(roleTypeInstance);
+         return name;
+      }
+      catch (Exception ex)
+      {
+         throw new IdentityException("Error creating relationship name", ex);
+      }
+   }
+   
+   public EntityManager getEntityManager(IdentityStoreInvocationContext invocationContext)
+   {
+      return ((JpaIdentityStoreSessionImpl) invocationContext.getIdentityStoreSession()).getEntityManager();
+   }
+
+   public IdentityObject findIdentityObject(IdentityStoreInvocationContext invocationContext, String id)
+         throws IdentityException
+   {
+      try
+      {
+        Object identity = getEntityManager(invocationContext).createQuery("select i from " +
+              identityClass.getName() + " i where i." +
+              modelProperties.get(PROPERTY_IDENTITY_ID).getName() +
+              " = :id")
+              .setParameter("id", id)
+              .getSingleResult();
+        
+        IdentityObjectType type = modelProperties.containsKey(PROPERTY_IDENTITY_TYPE_NAME) ?
+              new IdentityObjectTypeImpl(
+                    modelProperties.get(PROPERTY_IDENTITY_TYPE_NAME).getValue(
+                          modelProperties.get(PROPERTY_IDENTITY_TYPE).getValue(identity)).toString()) :
+              new IdentityObjectTypeImpl(modelProperties.get(PROPERTY_IDENTITY_TYPE).getValue(identity).toString());
+        
+        
+        return new IdentityObjectImpl(
+                  modelProperties.get(PROPERTY_IDENTITY_ID).getValue(identity).toString(),
+                  modelProperties.get(PROPERTY_IDENTITY_NAME).getValue(identity).toString(),
+                  type);
+      }
+      catch (NoResultException ex)
+      {
+         return null;
+      }
+   }
+
+   public IdentityObject findIdentityObject(
+         IdentityStoreInvocationContext invocationContext, String name,
+         IdentityObjectType identityObjectType) throws IdentityException
+   {
+      try
+      {
+         Object identityType = modelProperties.containsKey(PROPERTY_IDENTITY_TYPE_NAME) ?
+               lookupIdentityType(identityObjectType.getName(), getEntityManager(invocationContext)) : 
+                  identityObjectType.getName();
+         
+         Object identity = getEntityManager(invocationContext).createQuery("select i from " +
+              identityClass.getName() + " i where i." +
+              modelProperties.get(PROPERTY_IDENTITY_NAME).getName() +
+              " = :name and i." + modelProperties.get(PROPERTY_IDENTITY_TYPE).getName() + 
+              " = :type")
+              .setParameter("name", name)
+              .setParameter("type", identityType)              
+              .getSingleResult();
+        
+        return new IdentityObjectImpl(
+                  modelProperties.get(PROPERTY_IDENTITY_ID).getValue(identity).toString(),
+                  modelProperties.get(PROPERTY_IDENTITY_NAME).getValue(identity).toString(),
+                  identityObjectType);
+      }
+      catch (NoResultException ex)
+      {
+         return null;
+      }
+   }
+
+   public Collection<IdentityObject> findIdentityObject(
+         IdentityStoreInvocationContext ctx,
+         IdentityObjectType identityType, IdentityObjectSearchCriteria searchCriteria)
+         throws IdentityException
+   {
+      List<IdentityObject> objs = new ArrayList<IdentityObject>();
+      
+      EntityManager em = getEntityManager(ctx);
+      
+      CriteriaBuilder builder = em.getCriteriaBuilder();
+      CriteriaQuery<?> criteria = builder.createQuery(identityClass);
+      
+      Root<?> root = criteria.from(identityClass);
+
+      Property<?> identityTypeProp = modelProperties.get(PROPERTY_IDENTITY_TYPE);
+      
+      List<Predicate> predicates = new ArrayList<Predicate>();
+      
+      if (identityType != null)
+      {
+         predicates.add(builder.equal(root.get(identityTypeProp.getName()), 
+               lookupIdentityType(identityType.getName(), em)));
+      }
+      
+      criteria.where(predicates.toArray(new Predicate[0]));
+      
+      List<?> results = em.createQuery(criteria).getResultList();
+      
+      EntityToSpiConverter converter = new EntityToSpiConverter();
+      
+      for (Object result : results)
+      {               
+         objs.add(converter.convertToIdentityObject(result));
+      }
+      
+      return objs;
+   }
+
+   public Collection<IdentityObject> findIdentityObject(
+         IdentityStoreInvocationContext invocationCxt, IdentityObject identity,
+         IdentityObjectRelationshipType relationshipType, boolean parent,
+         IdentityObjectSearchCriteria criteria) throws IdentityException
+   {
+      List<IdentityObject> objs = new ArrayList<IdentityObject>();
+      
+      System.out.println("*** Invoked unimplemented method findIdentityObject()");
+      
+      // TODO Auto-generated method stub
+      return objs;
+   }
+
+   public String getId()
+   {
+      return id;
+   }
+
+   public int getIdentityObjectsCount(
+         IdentityStoreInvocationContext invocationCtx,
+         IdentityObjectType identityType) throws IdentityException
+   {
+      System.out.println("*** Invoked unimplemented method getIdentityObjectsCount()");
+      // TODO Auto-generated method stub
+      return 0;
+   }
+
+   public Map<String, String> getRelationshipNameProperties(
+         IdentityStoreInvocationContext ctx, String name)
+         throws IdentityException, OperationNotSupportedException
+   {
+      System.out.println("*** Invoked unimplemented method getRelationshipNameProperties()");
+      // TODO Auto-generated method stub
+      return null;
+   }
+
+   public Set<String> getRelationshipNames(IdentityStoreInvocationContext ctx,
+         IdentityObjectSearchCriteria searchCriteria) throws IdentityException,
+         OperationNotSupportedException
+   {
+      Set<String> names = new HashSet<String>();
+      
+      Property<Object> roleTypeNameProp = modelProperties.get(PROPERTY_ROLE_TYPE_NAME);
+      
+      if (roleTypeClass != null)
+      {
+         EntityManager em = getEntityManager(ctx);
+         
+         CriteriaBuilder builder = em.getCriteriaBuilder();
+         CriteriaQuery<?> criteria = builder.createQuery(roleTypeClass);
+         criteria.from(roleTypeClass);
+         
+         List<?> results = em.createQuery(criteria).getResultList();
+         for (Object result : results)
+         {
+            names.add(roleTypeNameProp.getValue(result).toString());
+         }
+      }      
+
+      return names;
+   }
+
+   public Set<String> getRelationshipNames(IdentityStoreInvocationContext ctx,
+         IdentityObject identity, IdentityObjectSearchCriteria searchCriteria)
+         throws IdentityException, OperationNotSupportedException
+   {
+      Set<String> names = new HashSet<String>();
+      
+      if (!featuresMetaData.isNamedRelationshipsSupported()) return names;
+      
+      EntityManager em = getEntityManager(ctx);
+      
+      CriteriaBuilder builder = em.getCriteriaBuilder();
+      CriteriaQuery<?> criteria = builder.createQuery(relationshipClass);
+      Root<?> root = criteria.from(relationshipClass);
+      
+      Property<?> identityToProperty = modelProperties.get(PROPERTY_RELATIONSHIP_TO);
+      Property<?> relationshipNameProperty = modelProperties.get(PROPERTY_RELATIONSHIP_NAME);
+      
+      List<Predicate> predicates = new ArrayList<Predicate>();
+      predicates.add(builder.equal(root.get(identityToProperty.getName()), 
+            lookupIdentity(identity, em)));
+      
+      criteria.where(predicates.toArray(new Predicate[0]));
+      
+      List<?> results = em.createQuery(criteria).getResultList();
+      for (Object result : results)
+      {
+         names.add((String) relationshipNameProperty.getValue(result));
+      }
+      
+      return names;
+   }
+
+   public Map<String, String> getRelationshipProperties(
+         IdentityStoreInvocationContext ctx,
+         IdentityObjectRelationship relationship) throws IdentityException,
+         OperationNotSupportedException
+   {
+      System.out.println("*** Invoked unimplemented method getRelationshipProperties()");
+      // TODO Auto-generated method stub
+      return null;
+   }
+
+   public FeaturesMetaData getSupportedFeatures()
+   {      
+      return featuresMetaData;
+   }
+
+   public void removeIdentityObject(
+         IdentityStoreInvocationContext ctx, IdentityObject identity)
+         throws IdentityException
+   {
+      removeRelationships(ctx, identity, null, false);
+      
+      Property<?> nameProperty = modelProperties.get(PROPERTY_IDENTITY_NAME);
+      Property<?> typeProperty = modelProperties.get(PROPERTY_IDENTITY_TYPE);
+      
+      EntityManager em = getEntityManager(ctx);
+      
+      CriteriaBuilder builder = em.getCriteriaBuilder();
+      
+      CriteriaQuery<?> criteria = builder.createQuery(identityClass);
+      Root<?> root = criteria.from(identityClass);
+      
+      List<Predicate> predicates = new ArrayList<Predicate>();
+      predicates.add(builder.equal(root.get(nameProperty.getName()), 
+            identity.getName()));
+      predicates.add(builder.equal(root.get(typeProperty.getName()),
+            lookupIdentityType(identity.getIdentityType().getName(), em)));
+      
+      criteria.where(predicates.toArray(new Predicate[0]));
+      
+      try
+      {
+         Object instance = em.createQuery(criteria).getSingleResult();
+                  
+         // If there is a credential class, delete any credentials
+         if (credentialClass != null)
+         {
+            Property<?> credentialIdentityProp = modelProperties.get(PROPERTY_CREDENTIAL_IDENTITY);
+            
+            criteria = builder.createQuery(credentialClass);
+            root = criteria.from(credentialClass);
+            
+            predicates = new ArrayList<Predicate>();
+            predicates.add(builder.equal(root.get(credentialIdentityProp.getName()),
+                  lookupIdentity(identity, em)));
+            criteria.where(predicates.toArray(new Predicate[0]));
+            
+            List<?> results = em.createQuery(criteria).getResultList();
+            for (Object result : results)
+            {
+               em.remove(result);
+            }
+         }
+         
+         em.remove(instance);
+      }
+      catch (NoResultException ex)
+      {
+         throw new IdentityException(String.format(
+               "Exception removing identity object - [%s] not found.", 
+               identity), ex);
+      }
+   }
+
+   public void removeRelationship(IdentityStoreInvocationContext ctx,
+         IdentityObject fromIdentity, IdentityObject toIdentity,
+         IdentityObjectRelationshipType relationshipType,
+         String relationshipName) throws IdentityException
+   {
+      Property<?> fromProperty = modelProperties.get(PROPERTY_RELATIONSHIP_FROM);
+      Property<?> toProperty = modelProperties.get(PROPERTY_RELATIONSHIP_TO);
+      Property<?> relationshipTypeProp = modelProperties.get(PROPERTY_RELATIONSHIP_TYPE);
+      
+      EntityManager em = getEntityManager(ctx);
+
+      CriteriaBuilder builder = em.getCriteriaBuilder();
+      CriteriaQuery<?> criteria = builder.createQuery(identityClass);
+      Root<?> root = criteria.from(identityClass);
+      
+      List<Predicate> predicates = new ArrayList<Predicate>();
+      predicates.add(builder.equal(root.get(fromProperty.getName()), 
+            lookupIdentity(fromIdentity, em)));
+      predicates.add(builder.equal(root.get(toProperty.getName()), 
+            lookupIdentity(toIdentity, em)));
+      predicates.add(builder.equal(root.get(relationshipTypeProp.getName()), 
+            lookupRelationshipType(relationshipType, em)));
+      
+      criteria.where(predicates.toArray(new Predicate[0]));
+      
+      Object relationship = em.createQuery(criteria).getSingleResult();
+      em.remove(relationship);
+   }
+
+   public String removeRelationshipName(IdentityStoreInvocationContext ctx,
+         String name) throws IdentityException, OperationNotSupportedException
+   {
+      Property<?> nameProp = modelProperties.get(PROPERTY_ROLE_TYPE_NAME);
+      EntityManager em = getEntityManager(ctx);
+      
+      CriteriaBuilder builder = em.getCriteriaBuilder();
+      CriteriaQuery<?> criteria = builder.createQuery(roleTypeClass);
+      Root<?> root = criteria.from(roleTypeClass);
+      
+      List<Predicate> predicates = new ArrayList<Predicate>();
+      predicates.add(builder.equal(root.get(nameProp.getName()), name));
+      criteria.where(predicates.toArray((new Predicate[0])));
+      Object roleType = em.createQuery(criteria).getSingleResult();
+      em.remove(roleType);
+      
+      return null;
+   }
+
+   public void removeRelationshipNameProperties(
+         IdentityStoreInvocationContext ctx, String name, Set<String> properties)
+         throws IdentityException, OperationNotSupportedException
+   {
+      // TODO Auto-generated method stub
+      System.out.println("*** Invoked unimplemented method removeRelationshipNameProperties()");
+   }
+
+   public void removeRelationshipProperties(IdentityStoreInvocationContext ctx,
+         IdentityObjectRelationship relationship, Set<String> properties)
+         throws IdentityException, OperationNotSupportedException
+   {
+      // TODO Auto-generated method stub
+      System.out.println("*** Invoked unimplemented method removeRelationshipProperties()");
+   }
+
+   public void removeRelationships(
+         IdentityStoreInvocationContext ctx,
+         IdentityObject identity1, IdentityObject identity2, boolean named)
+         throws IdentityException
+   {
+      EntityManager em = getEntityManager(ctx);
+      
+      CriteriaBuilder builder = em.getCriteriaBuilder();
+      CriteriaQuery<?> criteria = builder.createQuery(relationshipClass);
+      Root<?> root = criteria.from(relationshipClass);
+      
+      Property<?> relationshipFromProp = modelProperties.get(PROPERTY_RELATIONSHIP_FROM);
+      Property<?> relationshipToProp = modelProperties.get(PROPERTY_RELATIONSHIP_TO);
+      
+      List<Predicate> predicates = new ArrayList<Predicate>();
+      
+      if (identity1 != null)
+      {
+         predicates.add(builder.equal(root.get(relationshipFromProp.getName()),
+               lookupIdentity(identity1, em)));
+      }
+      
+      if (identity2 != null)
+      {
+         predicates.add(builder.equal(root.get(relationshipToProp.getName()),
+               lookupIdentity(identity2, em)));
+      }
+      
+      criteria.where(predicates.toArray(new Predicate[0]));
+      
+      List<?> results = em.createQuery(criteria).getResultList();
+      for (Object result : results)
+      {
+         em.remove(result);
+      }
+      
+      criteria = builder.createQuery(relationshipClass);
+      criteria.from(relationshipClass);
+      
+      predicates = new ArrayList<Predicate>();
+      
+      if (identity2 != null)
+      {
+         predicates.add(builder.equal(root.get(relationshipFromProp.getName()),
+               lookupIdentity(identity2, em)));
+      }
+      
+      if (identity1 != null)
+      {
+         predicates.add(builder.equal(root.get(relationshipToProp.getName()),
+               lookupIdentity(identity1, em)));
+      }
+      
+      criteria.where(predicates.toArray(new Predicate[0]));
+      
+      results = em.createQuery(criteria).getResultList();
+      for (Object result : results)
+      {
+         em.remove(result);
+      }
+   }
+
+   public Set<IdentityObjectRelationship> resolveRelationships(
+         IdentityStoreInvocationContext ctx,
+         IdentityObject fromIdentity, IdentityObject toIdentity,
+         IdentityObjectRelationshipType relationshipType)
+         throws IdentityException
+   {
+      Set<IdentityObjectRelationship> relationships = new HashSet<IdentityObjectRelationship>();
+      
+      EntityManager em = getEntityManager(ctx);
+      
+      CriteriaBuilder builder = em.getCriteriaBuilder();
+      CriteriaQuery<?> criteria = builder.createQuery(relationshipClass);
+      Root<?> root = criteria.from(relationshipClass);
+      
+      Property<?> relationshipFromProp = modelProperties.get(PROPERTY_RELATIONSHIP_FROM);
+      Property<?> relationshipToProp = modelProperties.get(PROPERTY_RELATIONSHIP_TO);
+      Property<?> relationshipTypeProp = modelProperties.get(PROPERTY_RELATIONSHIP_TYPE);
+      Property<?> relationshipNameProp = modelProperties.get(PROPERTY_RELATIONSHIP_NAME);
+      
+      List<Predicate> predicates = new ArrayList<Predicate>();
+      
+      if (fromIdentity != null)
+      {
+         predicates.add(builder.equal(root.get(relationshipFromProp.getName()), 
+            lookupIdentity(fromIdentity, em)));
+      }
+      
+      if (toIdentity != null)
+      {
+         predicates.add(builder.equal(root.get(relationshipToProp.getName()),
+            lookupIdentity(toIdentity, em)));
+      }
+      
+      if (relationshipType != null)
+      {
+         predicates.add(builder.equal(root.get(relationshipTypeProp.getName()),
+               lookupRelationshipType(relationshipType, em)));
+      }
+      
+      criteria.where(predicates.toArray(new Predicate[0]));
+      
+      List<?> results = em.createQuery(criteria).getResultList();
+      
+      EntityToSpiConverter converter = new EntityToSpiConverter();
+      
+      for (Object result : results)
+      {
+         IdentityObjectRelationship relationship = new IdentityObjectRelationshipImpl(
+               converter.convertToIdentityObject(relationshipFromProp.getValue(result)),
+               converter.convertToIdentityObject(relationshipToProp.getValue(result)),
+               (String) relationshipNameProp.getValue(result),
+               converter.convertToRelationshipType(relationshipTypeProp.getValue(result))         
+         );
+         
+         relationships.add(relationship);
+      }
+      
+      return relationships;
+   }
+
+   public Set<IdentityObjectRelationship> resolveRelationships(
+         IdentityStoreInvocationContext ctx, IdentityObject identity,
+         IdentityObjectRelationshipType relationshipType, boolean parent,
+         boolean named, String name) throws IdentityException
+   {
+      Set<IdentityObjectRelationship> relationships = new HashSet<IdentityObjectRelationship>();
+      
+      EntityManager em = getEntityManager(ctx);
+      
+      CriteriaBuilder builder = em.getCriteriaBuilder();
+      CriteriaQuery<?> criteria = builder.createQuery(relationshipClass);
+      Root<?> root = criteria.from(relationshipClass);
+      
+      Property<?> relationshipFromProp = modelProperties.get(PROPERTY_RELATIONSHIP_FROM);
+      Property<?> relationshipToProp = modelProperties.get(PROPERTY_RELATIONSHIP_TO);
+      Property<?> relationshipTypeProp = modelProperties.get(PROPERTY_RELATIONSHIP_TYPE);
+      Property<?> relationshipNameProp = modelProperties.get(PROPERTY_RELATIONSHIP_NAME);
+      
+      List<Predicate> predicates = new ArrayList<Predicate>();
+      
+      if (parent)
+      {
+         predicates.add(builder.equal(root.get(relationshipFromProp.getName()),
+               lookupIdentity(identity, em)));
+      }
+      else
+      {
+         predicates.add(builder.equal(root.get(relationshipToProp.getName()), 
+               lookupIdentity(identity, em)));
+      }
+            
+      if (relationshipType != null)
+      {
+         predicates.add(builder.equal(root.get(relationshipTypeProp.getName()),
+               lookupRelationshipType(relationshipType, em)));
+      }
+      
+      if (named)
+      {
+         if (name != null)
+         {
+            predicates.add(builder.equal(root.get(relationshipNameProp.getName()),
+               name));
+         }
+         else
+         {
+            predicates.add(builder.isNotNull(root.get(relationshipNameProp.getName())));
+         }
+      }
+      
+      criteria.where(predicates.toArray(new Predicate[0]));
+      
+      List<?> results = em.createQuery(criteria).getResultList();
+      
+      EntityToSpiConverter converter = new EntityToSpiConverter();
+      
+      for (Object result : results)
+      {
+         IdentityObjectRelationship relationship = new IdentityObjectRelationshipImpl(
+               converter.convertToIdentityObject(relationshipFromProp.getValue(result)),
+               converter.convertToIdentityObject(relationshipToProp.getValue(result)),
+               (String) relationshipNameProp.getValue(result),
+               converter.convertToRelationshipType(relationshipTypeProp.getValue(result))         
+         );
+         
+         relationships.add(relationship);
+      }
+      
+      return relationships;
+   }
+
+   public void setRelationshipNameProperties(
+         IdentityStoreInvocationContext ctx, String name,
+         Map<String, String> properties) throws IdentityException,
+         OperationNotSupportedException
+   {
+      // TODO Auto-generated method stub
+      System.out.println("*** Invoked unimplemented method setRelationshipNameProperties()");
+      
+   }
+
+   public void setRelationshipProperties(IdentityStoreInvocationContext ctx,
+         IdentityObjectRelationship relationship, Map<String, String> properties)
+         throws IdentityException, OperationNotSupportedException
+   {
+      // TODO Auto-generated method stub
+      System.out.println("*** Invoked unimplemented method setRelationshipProperties()");
+   }
+
+   public void updateCredential(IdentityStoreInvocationContext ctx,
+         IdentityObject identityObject, IdentityObjectCredential credential)
+         throws IdentityException
+   {
+      EntityManager em = getEntityManager(ctx);
+      
+      Property<Object> credentialValue = modelProperties.get(PROPERTY_CREDENTIAL_VALUE);
+      
+      if (credentialClass != null)
+      {
+         Property<Object> credentialIdentity = modelProperties.get(PROPERTY_CREDENTIAL_IDENTITY);
+         Property<Object> credentialType = modelProperties.get(PROPERTY_CREDENTIAL_TYPE);
+         Object identity = lookupIdentity(identityObject, em);
+         
+         CriteriaBuilder builder = em.getCriteriaBuilder();
+         CriteriaQuery<?> criteria = builder.createQuery(credentialClass);
+         Root<?> root = criteria.from(credentialClass);
+         
+         List<Predicate> predicates = new ArrayList<Predicate>();
+         predicates.add(builder.equal(root.get(credentialIdentity.getName()),
+               identity));
+         
+         if (credentialType != null)
+         {
+            if (String.class.equals(credentialType.getJavaClass()))
+            {
+               predicates.add(builder.equal(root.get(credentialType.getName()),
+                     credential.getType().getName()));
+            }
+            else
+            {
+               predicates.add(builder.equal(root.get(credentialType.getName()),
+                     lookupCredentialTypeEntity(credential.getType().getName(), em)));
+            }
+         }
+         
+         criteria.where(predicates.toArray(new Predicate[0]));
+         
+         List<?> results = em.createQuery(criteria).getResultList();
+         
+         if (results.isEmpty())
+         {
+            // The credential doesn't exist, let's create it
+            try
+            {
+               Object newCredential = credentialClass.newInstance();
+               credentialIdentity.setValue(newCredential, identity);
+               credentialValue.setValue(newCredential, credential.getValue());
+               credentialType.setValue(newCredential, 
+                     lookupCredentialTypeEntity(credential.getType().getName(), em));
+               
+               em.persist(newCredential);
+            }
+            catch (IllegalAccessException ex)
+            {
+               throw new IdentityException("Error updating credential - could " +
+                     "not create credential instance", ex);
+            }
+            catch (InstantiationException ex)
+            {
+               throw new IdentityException("Error updating credential - could " +
+                     "not create credential instance", ex);
+            }
+         }
+         else
+         {
+            // TODO there shouldn't be multiple credentials with the same type,
+            // but if there are, we need to deal with it somehow.. for now just use the first one
+            
+            Object result = results.get(0);
+            credentialValue.setValue(result, credential.getValue());
+            
+            em.merge(result);
+         }
+      }
+      else
+      {
+         // The credential is stored in the identity class, update it there
+         
+         Property<Object> credentialProp = modelProperties.get(PROPERTY_CREDENTIAL_VALUE);
+         Object identity = lookupIdentity(identityObject, em);
+         
+         credentialProp.setValue(identity, credential.getValue());
+         
+         em.merge(identity);         
+      }
+
+   }
+
+   public boolean validateCredential(IdentityStoreInvocationContext ctx,
+         IdentityObject identityObject, IdentityObjectCredential credential)
+         throws IdentityException
+   {
+      EntityManager em = getEntityManager(ctx);
+
+      Property<?> credentialValue = modelProperties.get(PROPERTY_CREDENTIAL_VALUE);
+      
+      // Either credentials are stored in their own class...
+      if (credentialClass != null)
+      {
+         Property<?> credentialIdentity = modelProperties.get(PROPERTY_CREDENTIAL_IDENTITY);
+         Property<?> credentialType = modelProperties.get(PROPERTY_CREDENTIAL_TYPE);
+         
+         CriteriaBuilder builder = em.getCriteriaBuilder();
+         CriteriaQuery<?> criteria = builder.createQuery(credentialClass);
+         Root<?> root = criteria.from(credentialClass);
+         
+         List<Predicate> predicates = new ArrayList<Predicate>();
+         predicates.add(builder.equal(root.get(credentialIdentity.getName()), 
+               lookupIdentity(identityObject, em)));
+         
+         if (credentialType != null)
+         {
+            if (String.class.equals(credentialType.getJavaClass()))
+            {
+               predicates.add(builder.equal(root.get(credentialType.getName()),
+                     credential.getType().getName()));
+            }
+            else
+            {
+               predicates.add(builder.equal(root.get(credentialType.getName()),
+                     lookupCredentialTypeEntity(credential.getType().getName(), em)));
+            }
+         }
+         
+         criteria.where(predicates.toArray(new Predicate[0]));
+         
+         List<?> results = em.createQuery(criteria).getResultList();
+         
+         if (results.isEmpty()) return false;
+         
+         // TODO this only supports plain text passwords
+         
+         for (Object result : results)
+         {
+            Object val = credentialValue.getValue(result);
+            if (val.equals(credential.getValue())) return true;
+         }
+      }
+      // or they're stored in the identity class
+      else
+      {
+         Property<?> identityNameProp = modelProperties.get(PROPERTY_IDENTITY_NAME);
+         
+         CriteriaBuilder builder = em.getCriteriaBuilder();
+         CriteriaQuery<?> criteria = builder.createQuery(credentialValue.getDeclaringClass());
+         
+         Root<?> root = criteria.from(credentialValue.getDeclaringClass());
+         
+         List<Predicate> predicates = new ArrayList<Predicate>();
+         predicates.add(builder.equal(root.get(identityNameProp.getName()), 
+               identityObject.getName()));
+         
+         criteria.where(predicates.toArray(new Predicate[0]));
+         
+         Object result = em.createQuery(criteria).getSingleResult();
+         
+         Object val = credentialValue.getValue(result);
+         if (val.equals(credential.getValue())) return true;
+      }
+
+      return false;
+   }
+
+   public void addAttributes(IdentityStoreInvocationContext invocationCtx,
+         IdentityObject identity, IdentityObjectAttribute[] attributes)
+         throws IdentityException
+   {
+      // TODO Auto-generated method stub
+      
+   }
+
+   public IdentityObject findIdentityObjectByUniqueAttribute(
+         IdentityStoreInvocationContext invocationCtx,
+         IdentityObjectType identityObjectType,
+         IdentityObjectAttribute attribute) throws IdentityException
+   {
+      // TODO Auto-generated method stub
+      return null;
+   }
+
+   public IdentityObjectAttribute getAttribute(IdentityStoreInvocationContext ctx,
+         IdentityObject identity, String name) throws IdentityException
+   {
+      EntityManager em = getEntityManager(ctx);
+      
+      Property<?> attributeProperty = attributeProperties.get(name);
+      if (attributeProperty != null)
+      {
+         // TODO implement attribute search for attributes scattered across the model
+         
+         
+         return new SimpleAttribute(name);
+      }
+      else
+      {
+         // If there is no attributeClass set, we have nowhere else to look - return an empty attribute
+         if (attributeClass == null) return new SimpleAttribute(name);
+         
+         Property<?> attributeIdentityProp = modelProperties.get(PROPERTY_ATTRIBUTE_IDENTITY);
+         Property<?> attributeNameProp = modelProperties.get(PROPERTY_ATTRIBUTE_NAME);
+         Property<?> attributeValueProp = modelProperties.get(PROPERTY_ATTRIBUTE_VALUE);
+         
+         CriteriaBuilder builder = em.getCriteriaBuilder();
+         CriteriaQuery<?> criteria = builder.createQuery(attributeClass);
+         Root<?> root = criteria.from(attributeClass);
+         
+         List<Predicate> predicates = new ArrayList<Predicate>();
+         predicates.add(builder.equal(root.get(attributeIdentityProp.getName()), 
+               lookupIdentity(identity, em)));
+         predicates.add(builder.equal(root.get(attributeNameProp.getName()),
+               name));
+         
+         criteria.where(predicates.toArray(new Predicate[0]));
+         
+         List<?> results = em.createQuery(criteria).getResultList();
+         
+         if (results.size() == 0)
+         {
+            // No results found, return an empty attribute value
+            return new SimpleAttribute(name);            
+         }
+         else if (results.size() == 1)
+         {
+            return new SimpleAttribute(name, attributeValueProp.getValue(results.get(0)));
+         }
+         else
+         {
+            Collection<Object> values = new ArrayList<Object>();
+            for (Object result : results)
+            {
+               values.add(attributeValueProp.getValue(result));               
+            }
+            
+            return new SimpleAttribute(name, values.toArray());
+         }
+      }
+   }
+
+   public Map<String, IdentityObjectAttribute> getAttributes(
+         IdentityStoreInvocationContext ctx,
+         IdentityObject identityObject) throws IdentityException
+   {
+      Map<String, IdentityObjectAttribute> attributes = new HashMap<String,IdentityObjectAttribute>();
+      
+      EntityManager em = getEntityManager(ctx);
+      
+      Object identity = lookupIdentity(identityObject, em);
+      
+      // TODO iterate through attributeProperties
+      
+      if (attributeClass != null)
+      {
+         Property<?> attributeIdentityProp = modelProperties.get(PROPERTY_ATTRIBUTE_IDENTITY);
+         Property<?> attributeNameProp = modelProperties.get(PROPERTY_ATTRIBUTE_NAME);
+         Property<?> attributeValueProp = modelProperties.get(PROPERTY_ATTRIBUTE_VALUE);
+         
+         CriteriaBuilder builder = em.getCriteriaBuilder();
+         CriteriaQuery<?> criteria = builder.createQuery(attributeClass);
+         Root<?> root = criteria.from(attributeClass);
+         
+         List<Predicate> predicates = new ArrayList<Predicate>();
+         predicates.add(builder.equal(root.get(attributeIdentityProp.getName()), 
+               identity));
+         
+         criteria.where(predicates.toArray(new Predicate[0]));
+         
+         List<?> results = em.createQuery(criteria).getResultList();
+
+         for (Object result : results)
+         {
+            String name = attributeNameProp.getValue(result).toString();
+            Object value = attributeValueProp.getValue(result);
+            
+            if (attributes.containsKey(name))
+            {
+               IdentityObjectAttribute attr = attributes.get(name);
+               attr.addValue(value);
+            }
+            else
+            {
+               attributes.put(name, new SimpleAttribute(name, value));
+            }
+         }
+      }
+      
+      return attributes;
+   }
+   
+   public Map<String, IdentityObjectAttributeMetaData> getAttributesMetaData(
+         IdentityStoreInvocationContext invocationContext,
+         IdentityObjectType identityType)
+   {
+      // TODO Auto-generated method stub
+      return null;
+   }
+
+   public Set<String> getSupportedAttributeNames(
+         IdentityStoreInvocationContext invocationContext,
+         IdentityObjectType identityType) throws IdentityException
+   {
+      // TODO Auto-generated method stub
+      return null;
+   }
+
+   public void removeAttributes(IdentityStoreInvocationContext invocationCtx,
+         IdentityObject identity, String[] attributeNames)
+         throws IdentityException
+   {
+      // TODO Auto-generated method stub
+      
+   }
+
+   public void updateAttributes(IdentityStoreInvocationContext invocationCtx,
+         IdentityObject identity, IdentityObjectAttribute[] attributes)
+         throws IdentityException
+   {
+      // TODO Auto-generated method stub
+      
+   }
+
+   public IdentityStoreSession createIdentityStoreSession()
+         throws IdentityException
+   {
+      return createIdentityStoreSession(null);
+   }
+}

Added: idm/trunk/picketlink-idm-jpa/src/main/java/org/picketlink/idm/impl/store/jpa/JpaIdentityStoreConfiguration.java
===================================================================
--- idm/trunk/picketlink-idm-jpa/src/main/java/org/picketlink/idm/impl/store/jpa/JpaIdentityStoreConfiguration.java	                        (rev 0)
+++ idm/trunk/picketlink-idm-jpa/src/main/java/org/picketlink/idm/impl/store/jpa/JpaIdentityStoreConfiguration.java	2011-02-07 10:18:43 UTC (rev 740)
@@ -0,0 +1,127 @@
+package org.picketlink.idm.impl.store.jpa;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.picketlink.idm.impl.configuration.metadata.IdentityStoreConfigurationMetaDataImpl;
+
+/**
+ * A convenience class for setting JpaIdentityStore configuration options.
+ *  
+ * @author Shane Bryzak
+ */
+public class JpaIdentityStoreConfiguration extends IdentityStoreConfiguration
+{
+   private Class<?> identityClass;
+   private Class<?> credentialClass;
+   private Class<?> relationshipClass;
+   private Class<?> roleTypeClass;
+   private Class<?> attributeClass;
+   
+   @Override
+   public String getId()
+   {
+      return (super.getId() == null) ? "jpa" : super.getId();
+   }   
+   
+   /**
+    * If the identityStoreClass hasn't been set, then return JpaIdentityStore
+    * by default.
+    */
+   @Override
+   public Class<?> getIdentityStoreClass()
+   {
+      return (super.getIdentityStoreClass() == null) ?
+            JpaIdentityStore.class : super.getIdentityStoreClass();
+   }
+   
+   public Class<?> getIdentityClass()
+   {
+      return identityClass;
+   }
+   
+   public void setIdentityClass(Class<?> identityClass)
+   {
+      this.identityClass = identityClass;
+   }
+   
+   public Class<?> getCredentialClass()
+   {
+      return credentialClass;
+   }
+   
+   public void setCredentialClass(Class<?> credentialClass)
+   {
+      this.credentialClass = credentialClass;
+   }
+
+   public Class<?> getRelationshipClass()
+   {
+      return relationshipClass;
+   }
+   
+   public void setRelationshipClass(Class<?> relationshipClass)
+   {
+      this.relationshipClass = relationshipClass;
+   }
+
+   public Class<?> getRoleTypeClass()
+   {
+      return roleTypeClass;
+   }
+   
+   public void setRoleTypeClass(Class<?> roleTypeClass)
+   {
+      this.roleTypeClass = roleTypeClass;
+   }
+
+   public Class<?> getAttributeClass()
+   {
+      return attributeClass;
+   }
+   
+   public void setAttributeClass(Class<?> attributeClass)
+   {
+      this.attributeClass = attributeClass;
+   }
+   
+   public void doConfigure(IdentityStoreConfigurationMetaDataImpl store)
+   {
+      Map<String,List<String>> options = new HashMap<String,List<String>>();
+      
+      if (identityClass != null)
+      {
+         options.put(JpaIdentityStore.OPTION_IDENTITY_CLASS_NAME, 
+            createOptionList(identityClass.getName()));
+      }
+      
+      if (credentialClass != null)
+      {
+         options.put(JpaIdentityStore.OPTION_CREDENTIAL_CLASS_NAME, 
+            createOptionList(credentialClass.getName()));
+      }
+      
+      if (relationshipClass != null)
+      {
+         options.put(JpaIdentityStore.OPTION_RELATIONSHIP_CLASS_NAME, 
+            createOptionList(relationshipClass.getName()));
+      }
+      
+      if (roleTypeClass != null)
+      {
+         options.put(JpaIdentityStore.OPTION_ROLE_TYPE_CLASS_NAME, 
+            createOptionList(roleTypeClass.getName()));
+      }
+      
+      store.setOptions(options);      
+   }
+      
+   private List<String> createOptionList(String... values)
+   {
+      List<String> vals = new ArrayList<String>();
+      for (String v : values) vals.add(v);
+      return vals;
+   }   
+}

Added: idm/trunk/picketlink-idm-jpa/src/main/java/org/picketlink/idm/impl/store/jpa/JpaIdentityStoreSessionImpl.java
===================================================================
--- idm/trunk/picketlink-idm-jpa/src/main/java/org/picketlink/idm/impl/store/jpa/JpaIdentityStoreSessionImpl.java	                        (rev 0)
+++ idm/trunk/picketlink-idm-jpa/src/main/java/org/picketlink/idm/impl/store/jpa/JpaIdentityStoreSessionImpl.java	2011-02-07 10:18:43 UTC (rev 740)
@@ -0,0 +1,78 @@
+package org.picketlink.idm.impl.store.jpa;
+
+import javax.persistence.EntityManager;
+
+import org.picketlink.idm.common.exception.IdentityException;
+import org.picketlink.idm.spi.store.IdentityStoreSession;
+
+/**
+ * JPA-specific implementation of IdentityStoreSession, based on an EntityManager. 
+ * 
+ * @author Shane Bryzak
+ *
+ */
+public class JpaIdentityStoreSessionImpl implements IdentityStoreSession
+{
+   private EntityManager em;
+   
+   public JpaIdentityStoreSessionImpl(EntityManager em)
+   {
+      this.em = em;
+   }
+   
+   public EntityManager getEntityManager()
+   {
+      return em;
+   }
+   
+   public void clear() throws IdentityException
+   {
+      em.clear();      
+   }
+
+   public void close() throws IdentityException
+   {
+      em.close();
+   }
+
+   public void commitTransaction()
+   {
+      em.getTransaction().commit();
+   }
+
+   public Object getSessionContext() throws IdentityException
+   {
+      return em;
+   }
+
+   public boolean isOpen()
+   {
+      return em.isOpen();
+   }
+
+   public boolean isTransactionActive()
+   {
+      return em.getTransaction().isActive();
+   }
+
+   public boolean isTransactionSupported()
+   {
+      return true;
+   }
+
+   public void rollbackTransaction()
+   {
+      em.getTransaction().rollback();
+   }
+
+   public void save() throws IdentityException
+   {
+      em.flush();
+   }
+
+   public void startTransaction()
+   {
+      em.getTransaction().begin();
+   }
+
+}

Added: idm/trunk/picketlink-idm-jpa/src/main/java/org/picketlink/idm/impl/store/jpa/PropertyType.java
===================================================================
--- idm/trunk/picketlink-idm-jpa/src/main/java/org/picketlink/idm/impl/store/jpa/PropertyType.java	                        (rev 0)
+++ idm/trunk/picketlink-idm-jpa/src/main/java/org/picketlink/idm/impl/store/jpa/PropertyType.java	2011-02-07 10:18:43 UTC (rev 740)
@@ -0,0 +1,10 @@
+package org.picketlink.idm.impl.store.jpa;
+
+/**
+ * 
+ * @author Shane Bryzak
+ */
+public enum PropertyType {
+   NAME, TYPE, VALUE, RELATIONSHIP_FROM, RELATIONSHIP_TO, CREDENTIAL, 
+   CREDENTIAL_TYPE, ATTRIBUTE
+}

Modified: idm/trunk/pom.xml
===================================================================
--- idm/trunk/pom.xml	2011-02-05 18:39:26 UTC (rev 739)
+++ idm/trunk/pom.xml	2011-02-07 10:18:43 UTC (rev 740)
@@ -34,6 +34,7 @@
             <module>picketlink-idm-api</module>
             <module>picketlink-idm-core</module>
             <module>picketlink-idm-hibernate</module>
+            <module>picketlink-idm-jpa</module>
             <module>picketlink-idm-ldap</module>
             <module>picketlink-idm-cache</module>
             <module>picketlink-idm-auth</module>
@@ -51,6 +52,7 @@
             <module>picketlink-idm-api</module>
             <module>picketlink-idm-core</module>
             <module>picketlink-idm-hibernate</module>
+            <module>picketlink-idm-jpa</module>
             <module>picketlink-idm-ldap</module>
             <module>picketlink-idm-cache</module>
             <module>picketlink-idm-auth</module>
@@ -80,6 +82,7 @@
             <module>picketlink-idm-api</module>
             <module>picketlink-idm-core</module>
             <module>picketlink-idm-hibernate</module>
+            <module>picketlink-idm-jpa</module>
             <module>picketlink-idm-ldap</module>
             <module>picketlink-idm-cache</module>
             <module>picketlink-idm-auth</module>



More information about the jboss-cvs-commits mailing list