diff --git a/client/client.properties b/client/client.properties
new file mode 100644
index 0000000..9f3feee
--- /dev/null
+++ b/client/client.properties
@@ -0,0 +1,8 @@
+# Properties file with server URL settings for remote access.
+# Applied by PropertyPlaceholderConfigurer from "clientContext.xml".
+#
+
+serverName=localhost
+httpPort=8080
+contextPath=/spring-security-sample-contacts-filter
+rmiPort=1099
diff --git a/client/clientContext.xml b/client/clientContext.xml
new file mode 100644
index 0000000..d14785d
--- /dev/null
+++ b/client/clientContext.xml
@@ -0,0 +1,73 @@
+
+
+
+
+
+
+
+
+
+ client.properties
+
+
+
+
+
+
+
+
+
+ sample.contact.ContactManager
+
+
+ http://${serverName}:${httpPort}${contextPath}/remoting/ContactManager-httpinvoker
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..a01bd0d
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,267 @@
+
+
+ 4.0.0
+ org.springframework.security
+ spring-security-samples-contacts-xml
+ 3.2.0.RELEASE
+ war
+ spring-security-samples-contacts-xml
+ spring-security-samples-contacts-xml
+ http://spring.io/spring-security
+
+ spring.io
+ http://spring.io/
+
+
+
+ The Apache Software License, Version 2.0
+ http://www.apache.org/licenses/LICENSE-2.0.txt
+ repo
+
+
+
+
+ rwinch
+ Rob Winch
+ rwinch@gopivotal.com
+
+
+
+ scm:git:git://github.com/spring-projects/spring-security
+ scm:git:git://github.com/spring-projects/spring-security
+ https://github.com/spring-projects/spring-security
+
+
+
+
+ maven-compiler-plugin
+
+
+ 1.6
+
+
+
+ maven-war-plugin
+ 2.3
+
+ false
+
+
+
+
+
+
+
+
+
+ commons-dbcp
+ commons-dbcp
+ 20030825.184428
+ jar
+ compile
+
+
+ commons-pool
+ commons-pool
+ 20030825.183949
+ jar
+ compile
+
+
+
+
+
+ org.hibernate
+ hibernate-entitymanager
+ 3.6.0.Final
+ compile
+
+
+
+ org.hibernate.javax.persistence
+ hibernate-jpa-2.0-api
+ 1.0.0.Final
+ compile
+
+
+
+ org.apache.tiles
+ tiles-jsp
+ 2.2.2
+
+
+
+ org.springframework.security
+ spring-security-acl
+ 3.2.0.RELEASE
+ compile
+
+
+ org.springframework.security
+ spring-security-core
+ 3.2.0.RELEASE
+ compile
+
+
+ org.springframework
+ spring-aop
+ 3.2.6.RELEASE
+ compile
+
+
+ org.springframework
+ spring-beans
+ 3.2.6.RELEASE
+ compile
+
+
+ org.springframework
+ spring-orm
+ 3.2.6.RELEASE
+ jar
+ compile
+
+
+ org.springframework
+ spring-context
+ 3.2.6.RELEASE
+ compile
+
+
+ org.springframework
+ spring-core
+ 3.2.6.RELEASE
+ compile
+
+
+ commons-logging
+ commons-logging
+
+
+
+
+ org.springframework
+ spring-jdbc
+ 3.2.6.RELEASE
+ compile
+
+
+ org.springframework
+ spring-tx
+ 3.2.6.RELEASE
+ compile
+
+
+ org.springframework
+ spring-web
+ 3.2.6.RELEASE
+ compile
+
+
+ org.springframework
+ spring-webmvc
+ 3.2.6.RELEASE
+ compile
+
+
+ commons-logging
+ commons-logging
+ 1.1.1
+ compile
+ true
+
+
+ org.apache.tomcat
+ tomcat-servlet-api
+ 7.0.33
+ provided
+
+
+ ch.qos.logback
+ logback-classic
+ 0.9.29
+ runtime
+
+
+ javax.servlet
+ jstl
+ 1.2
+ runtime
+
+
+ net.sf.ehcache
+ ehcache
+ 1.6.2
+ runtime
+
+
+ org.hsqldb
+ hsqldb
+ 2.3.1
+ runtime
+
+
+ org.slf4j
+ jcl-over-slf4j
+ 1.7.5
+ runtime
+
+
+ org.springframework.security
+ spring-security-config
+ 3.2.0.RELEASE
+ runtime
+
+
+ org.springframework.security
+ spring-security-taglibs
+ 3.2.0.RELEASE
+ runtime
+
+
+ org.springframework.security
+ spring-security-web
+ 3.2.0.RELEASE
+ runtime
+
+
+ org.springframework
+ spring-context-support
+ 3.2.6.RELEASE
+ runtime
+
+
+ junit
+ junit
+ 4.10
+ test
+
+
+ org.easytesting
+ fest-assert
+ 1.4
+ test
+
+
+ org.mockito
+ mockito-core
+ 1.9.5
+ test
+
+
+ org.springframework
+ spring-test
+ 3.2.6.RELEASE
+ test
+
+
+ org.apache.derby
+ derbyclient
+ 10.10.1.1
+
+
+
+ /sample
+
+
diff --git a/src/main/java/org/springframework/security/samples/contacts/client/ClientApplication.java b/src/main/java/org/springframework/security/samples/contacts/client/ClientApplication.java
new file mode 100644
index 0000000..d77b120
--- /dev/null
+++ b/src/main/java/org/springframework/security/samples/contacts/client/ClientApplication.java
@@ -0,0 +1,142 @@
+/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.security.samples.contacts.client;
+
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.List;
+import java.util.Map;
+
+import org.springframework.beans.factory.ListableBeanFactory;
+import org.springframework.context.support.FileSystemXmlApplicationContext;
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.samples.contacts.entity.Contact;
+import org.springframework.security.samples.contacts.service.ContactManager;
+import org.springframework.util.StopWatch;
+
+
+/**
+ * Demonstrates accessing the {@link ContactManager} via remoting protocols.
+ *
+ * Based on Spring's JPetStore sample, written by Juergen Hoeller.
+ *
+ * @author Ben Alex
+ */
+public class ClientApplication {
+ //~ Instance fields ================================================================================================
+
+ private final ListableBeanFactory beanFactory;
+
+ //~ Constructors ===================================================================================================
+
+ public ClientApplication(ListableBeanFactory beanFactory) {
+ this.beanFactory = beanFactory;
+ }
+
+ //~ Methods ========================================================================================================
+
+ public void invokeContactManager(Authentication authentication, int nrOfCalls) {
+ StopWatch stopWatch = new StopWatch(nrOfCalls + " ContactManager call(s)");
+ Map contactServices = this.beanFactory.getBeansOfType(ContactManager.class, true, true);
+
+ SecurityContextHolder.getContext().setAuthentication(authentication);
+
+ for (String beanName : contactServices.keySet()) {
+ Object object = this.beanFactory.getBean("&" + beanName);
+
+ try {
+ System.out.println("Trying to find setUsername(String) method on: " + object.getClass().getName());
+
+ Method method = object.getClass().getMethod("setUsername", new Class[] {String.class});
+ System.out.println("Found; Trying to setUsername(String) to " + authentication.getPrincipal());
+ method.invoke(object, authentication.getPrincipal());
+ } catch (NoSuchMethodException ignored) {
+ System.out.println("This client proxy factory does not have a setUsername(String) method");
+ } catch (IllegalAccessException ignored) {
+ ignored.printStackTrace();
+ } catch (InvocationTargetException ignored) {
+ ignored.printStackTrace();
+ }
+
+ try {
+ System.out.println("Trying to find setPassword(String) method on: " + object.getClass().getName());
+
+ Method method = object.getClass().getMethod("setPassword", new Class[] {String.class});
+ method.invoke(object, authentication.getCredentials());
+ System.out.println("Found; Trying to setPassword(String) to " + authentication.getCredentials());
+ } catch (NoSuchMethodException ignored) {
+ System.out.println("This client proxy factory does not have a setPassword(String) method");
+ } catch (IllegalAccessException ignored) {}
+ catch (InvocationTargetException ignored) {}
+
+ ContactManager remoteContactManager = contactServices.get(beanName);
+ System.out.println("Calling ContactManager '" + beanName + "'");
+
+ stopWatch.start(beanName);
+
+ List contacts = null;
+
+ for (int i = 0; i < nrOfCalls; i++) {
+ contacts = remoteContactManager.getAll();
+ }
+
+ stopWatch.stop();
+
+ if (contacts.size() != 0) {
+ for(Contact contact : contacts) {
+ System.out.println("Contact: " + contact);
+ }
+ } else {
+ System.out.println("No contacts found which this user has permission to");
+ }
+
+ System.out.println();
+ System.out.println(stopWatch.prettyPrint());
+ }
+
+ SecurityContextHolder.clearContext();
+ }
+
+ public static void main(String[] args) {
+ String username = System.getProperty("username", "");
+ String password = System.getProperty("password", "");
+ String nrOfCallsString = System.getProperty("nrOfCalls", "");
+
+ if ("".equals(username) || "".equals(password)) {
+ System.out.println(
+ "You need to specify the user ID to use, the password to use, and optionally a number of calls "
+ + "using the username, password, and nrOfCalls system properties respectively. eg for user rod, "
+ + "use: -Dusername=rod -Dpassword=koala' for a single call per service and "
+ + "use: -Dusername=rod -Dpassword=koala -DnrOfCalls=10 for ten calls per service.");
+ System.exit(-1);
+ } else {
+ int nrOfCalls = 1;
+
+ if (!"".equals(nrOfCallsString)) {
+ nrOfCalls = Integer.parseInt(nrOfCallsString);
+ }
+
+ ListableBeanFactory beanFactory = new FileSystemXmlApplicationContext("clientContext.xml");
+ ClientApplication client = new ClientApplication(beanFactory);
+
+ client.invokeContactManager(new UsernamePasswordAuthenticationToken(username, password), nrOfCalls);
+ System.exit(0);
+ }
+ }
+}
diff --git a/src/main/java/org/springframework/security/samples/contacts/dao/AclDao.java b/src/main/java/org/springframework/security/samples/contacts/dao/AclDao.java
new file mode 100644
index 0000000..683df0a
--- /dev/null
+++ b/src/main/java/org/springframework/security/samples/contacts/dao/AclDao.java
@@ -0,0 +1,38 @@
+package org.springframework.security.samples.contacts.dao;
+
+import java.io.Serializable;
+import java.util.List;
+
+import org.springframework.security.acls.model.ObjectIdentity;
+import org.springframework.security.samples.contacts.entity.AclClass;
+import org.springframework.security.samples.contacts.entity.AclEntry;
+import org.springframework.security.samples.contacts.entity.AclObjectIdentity;
+import org.springframework.security.samples.contacts.entity.AclSid;
+
+public interface AclDao {
+
+ List findChildren(Serializable identifier, String type);
+
+ AclObjectIdentity getObjectIdentity(String type, Serializable identifier);
+
+ void createObjectIdentity(AclObjectIdentity identity);
+
+ List findAclSidList(Boolean valueOf, String sidName);
+
+ AclSid createAclSid(AclSid sid2);
+
+ List findAclClassList(String type);
+
+ AclClass createAclClass(AclClass clazz);
+
+ void deleteEntries(AclObjectIdentity oidPrimaryKey);
+
+ void deleteObjectIdentity(AclObjectIdentity oidPrimaryKey);
+
+ void createEntries(List entries);
+
+ boolean updateObjectIdentity(AclObjectIdentity aclObject);
+
+ AclSid findAclSid(String principal);
+
+}
diff --git a/src/main/java/org/springframework/security/samples/contacts/dao/ContactDao.java b/src/main/java/org/springframework/security/samples/contacts/dao/ContactDao.java
new file mode 100644
index 0000000..8ceb1ab
--- /dev/null
+++ b/src/main/java/org/springframework/security/samples/contacts/dao/ContactDao.java
@@ -0,0 +1,49 @@
+/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.security.samples.contacts.dao;
+
+import java.util.List;
+
+import org.springframework.security.samples.contacts.entity.Contact;
+import org.springframework.stereotype.Repository;
+
+
+
+/**
+ * Provides access to the application's persistence layer.
+ *
+ * @author Ben Alex
+ */
+@Repository
+public interface ContactDao {
+ //~ Methods ========================================================================================================
+
+ public Contact create(Contact contact);
+
+ public void delete(Long contactId);
+
+ public List findAll();
+
+ public List findAllPrincipals();
+
+ public List findAllRoles();
+
+ public Contact getById(Long id);
+
+ public void update(Contact contact);
+
+ public void delete(Contact contact);
+}
diff --git a/src/main/java/org/springframework/security/samples/contacts/dao/UserDao.java b/src/main/java/org/springframework/security/samples/contacts/dao/UserDao.java
new file mode 100644
index 0000000..f727f57
--- /dev/null
+++ b/src/main/java/org/springframework/security/samples/contacts/dao/UserDao.java
@@ -0,0 +1,11 @@
+package org.springframework.security.samples.contacts.dao;
+
+import org.springframework.security.samples.contacts.entity.User;
+
+
+
+public interface UserDao {
+
+ User findByUsername(String username);
+
+}
diff --git a/src/main/java/org/springframework/security/samples/contacts/dao/impl/AclDaoJpa.java b/src/main/java/org/springframework/security/samples/contacts/dao/impl/AclDaoJpa.java
new file mode 100644
index 0000000..0fd4e09
--- /dev/null
+++ b/src/main/java/org/springframework/security/samples/contacts/dao/impl/AclDaoJpa.java
@@ -0,0 +1,128 @@
+package org.springframework.security.samples.contacts.dao.impl;
+
+import java.io.Serializable;
+import java.util.List;
+
+import javax.persistence.EntityManager;
+import javax.persistence.PersistenceContext;
+import javax.persistence.Query;
+
+import org.springframework.security.acls.model.AccessControlEntry;
+import org.springframework.security.acls.model.ObjectIdentity;
+import org.springframework.security.samples.contacts.dao.AclDao;
+import org.springframework.security.samples.contacts.entity.AclClass;
+import org.springframework.security.samples.contacts.entity.AclEntry;
+import org.springframework.security.samples.contacts.entity.AclObjectIdentity;
+import org.springframework.security.samples.contacts.entity.AclSid;
+import org.springframework.stereotype.Repository;
+import org.springframework.transaction.annotation.Transactional;
+
+@Repository
+public class AclDaoJpa implements AclDao {
+
+
+ @PersistenceContext
+ private EntityManager entityManager;
+
+ @Override
+ public List findChildren(Serializable identifier, String type) {
+ Query query = entityManager.createQuery("select aoi from AclObjectIdentity aoi, AclObjectIdentity parent, AclClass aclClass where aoi.parentObject = parent and aoi.objIdClass = aclClass and parent.objIdIdentity = :objIdIdentity and parent.objIdClass = (select acl FROM AclClass acl where acl.clazz = :clazz)");
+ query.setParameter("objIdIdentity", identifier);
+ query.setParameter("clazz", type);
+
+ return query.getResultList();
+ }
+
+ @Override
+ public AclObjectIdentity getObjectIdentity(String type, Serializable identifier) {
+ Query query = entityManager.createQuery("select aoi from AclObjectIdentity aoi, AclClass aclClass where aoi.objIdIdentity = :objIdIdentity and aoi.objIdClass = aclClass and aclClass.clazz = :clazz)");
+ query.setParameter("objIdIdentity", identifier);
+ query.setParameter("clazz", type);
+
+ return (AclObjectIdentity) query.getSingleResult();
+ }
+
+ @Override
+ @Transactional
+ public void createObjectIdentity(AclObjectIdentity identity) {
+ // TODO Auto-generated method stub
+ entityManager.persist(identity);
+ }
+
+ @Override
+ public List findAclSidList(Boolean principal, String sidName) {
+ Query query = entityManager.createQuery("select sid from AclSid sid where sid.principal=:principal and sid.sid=:sid");
+ query.setParameter("principal", principal);
+ query.setParameter("sid", sidName);
+ return query.getResultList();
+ }
+
+ @Override
+ @Transactional
+ public AclSid createAclSid(AclSid sid2) {
+ entityManager.persist(sid2);
+ return sid2;
+ }
+
+ @Override
+ public List findAclClassList(String type) {
+ Query query = entityManager.createQuery("select clazz from AclClass clazz where clazz.clazz=:clazz");
+
+ query.setParameter("clazz", type);
+ return query.getResultList();
+ }
+
+ @Override
+ @Transactional
+ public AclClass createAclClass(AclClass clazz) {
+ entityManager.persist(clazz);
+ return clazz;
+ }
+
+ @Override
+ @Transactional
+ public void deleteEntries(AclObjectIdentity objectIdentity) {
+ objectIdentity = entityManager.find(AclObjectIdentity.class, objectIdentity.getId());
+ if(objectIdentity.getEntries()!=null) {
+ for(AccessControlEntry entry:objectIdentity.getEntries()) {
+ entityManager.remove((AclEntry)entry);
+ }
+ }
+
+ }
+
+ @Override
+ public void deleteObjectIdentity(AclObjectIdentity oidPrimaryKey) {
+ // TODO Auto-generated method stub
+ entityManager.remove(oidPrimaryKey);
+ }
+
+ @Override
+ @Transactional
+ public void createEntries(List entries) {
+ for(AclEntry entry:entries) {
+ entityManager.persist(entry);
+ }
+
+ }
+
+ @Override
+ public boolean updateObjectIdentity(AclObjectIdentity aclObject) {
+ // TODO Auto-generated method stub
+ entityManager.merge(aclObject);
+ return true;
+ }
+
+ @Override
+ public AclSid findAclSid(String principal) {
+ Query query = entityManager.createQuery("select sid from AclSid sid where sid.sid=:sid");
+
+ query.setParameter("sid", principal);
+ List results = query.getResultList();
+ if(results.size()>0) {
+ return results.get(0);
+ }
+ return null;
+ }
+
+}
diff --git a/src/main/java/org/springframework/security/samples/contacts/dao/impl/ContactDaoJpa.java b/src/main/java/org/springframework/security/samples/contacts/dao/impl/ContactDaoJpa.java
new file mode 100644
index 0000000..10f4762
--- /dev/null
+++ b/src/main/java/org/springframework/security/samples/contacts/dao/impl/ContactDaoJpa.java
@@ -0,0 +1,76 @@
+package org.springframework.security.samples.contacts.dao.impl;
+
+import java.util.List;
+
+import javax.persistence.EntityManager;
+import javax.persistence.PersistenceContext;
+import javax.persistence.Query;
+
+import org.springframework.security.samples.contacts.dao.ContactDao;
+import org.springframework.security.samples.contacts.entity.Contact;
+import org.springframework.stereotype.Repository;
+import org.springframework.transaction.annotation.Transactional;
+
+@Repository
+public class ContactDaoJpa implements ContactDao {
+
+ @PersistenceContext
+ private EntityManager entityManager;
+
+
+ @Override
+ @Transactional
+ public Contact create(Contact contact) {
+ // TODO Auto-generated method stub
+ entityManager.persist(contact);
+ return contact;
+ }
+
+ @Override
+ @Transactional
+ public void delete(Long contactId) {
+ // TODO Auto-generated method stub
+ Contact contact = entityManager.find(Contact.class, contactId);
+ entityManager.remove(contact);
+ }
+
+ @Override
+ public List findAll() {
+ Query query = entityManager.createQuery("select u from Contact u");
+
+ return query.getResultList();
+ }
+
+ @Override
+ public List findAllPrincipals() {
+ Query query = entityManager.createQuery("select u.username from User u", String.class);
+ return query.getResultList();
+ }
+
+ @Override
+ public List findAllRoles() {
+ Query query = entityManager.createQuery("select u.name from Role u", String.class);
+ return query.getResultList();
+ }
+
+ @Override
+ public Contact getById(Long id) {
+
+ return entityManager.find(Contact.class, id);
+ }
+
+ @Override
+ @Transactional
+ public void update(Contact contact) {
+ // TODO Auto-generated method stub
+ entityManager.merge(contact);
+ }
+
+ @Override
+ @Transactional
+ public void delete(Contact contact) {
+ // TODO Auto-generated method stub
+ entityManager.remove(contact);
+ }
+
+}
diff --git a/src/main/java/org/springframework/security/samples/contacts/dao/impl/UserDaoJpa.java b/src/main/java/org/springframework/security/samples/contacts/dao/impl/UserDaoJpa.java
new file mode 100644
index 0000000..9749763
--- /dev/null
+++ b/src/main/java/org/springframework/security/samples/contacts/dao/impl/UserDaoJpa.java
@@ -0,0 +1,24 @@
+package org.springframework.security.samples.contacts.dao.impl;
+
+import javax.persistence.EntityManager;
+import javax.persistence.PersistenceContext;
+import javax.persistence.Query;
+
+import org.springframework.security.samples.contacts.dao.UserDao;
+import org.springframework.security.samples.contacts.entity.User;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public class UserDaoJpa implements UserDao {
+
+ @PersistenceContext
+ private EntityManager entityManager;
+
+ @Override
+ public User findByUsername(String username) {
+ Query query = entityManager.createQuery("select u from User u where u.username=:username");
+ query.setParameter("username", username);
+ return (User) query.getSingleResult();
+ }
+
+}
diff --git a/src/main/java/org/springframework/security/samples/contacts/entity/AclClass.java b/src/main/java/org/springframework/security/samples/contacts/entity/AclClass.java
new file mode 100644
index 0000000..ceef7ac
--- /dev/null
+++ b/src/main/java/org/springframework/security/samples/contacts/entity/AclClass.java
@@ -0,0 +1,31 @@
+package org.springframework.security.samples.contacts.entity;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.Table;
+
+@Entity
+@Table(name="ACL_CLASS")
+public class AclClass {
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.AUTO)
+ private Long id;
+ @Column(name="CLASS",unique=true)
+ private String clazz;
+ public Long getId() {
+ return id;
+ }
+ public void setId(Long id) {
+ this.id = id;
+ }
+ public String getClazz() {
+ return clazz;
+ }
+ public void setClazz(String clazz) {
+ this.clazz = clazz;
+ }
+}
diff --git a/src/main/java/org/springframework/security/samples/contacts/entity/AclEntry.java b/src/main/java/org/springframework/security/samples/contacts/entity/AclEntry.java
new file mode 100644
index 0000000..898c6cd
--- /dev/null
+++ b/src/main/java/org/springframework/security/samples/contacts/entity/AclEntry.java
@@ -0,0 +1,110 @@
+package org.springframework.security.samples.contacts.entity;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.Table;
+
+import org.springframework.security.acls.model.AccessControlEntry;
+import org.springframework.security.acls.model.Acl;
+import org.springframework.security.acls.model.Permission;
+
+@Entity
+@Table(name="ACL_ENTRY")
+public class AclEntry{
+ @Id
+ @GeneratedValue(strategy = GenerationType.AUTO)
+ private Long id;
+
+ @ManyToOne
+ @JoinColumn(name="ACL_OBJECT_IDENTITY")
+ private AclObjectIdentity aclObjectIdentity;
+
+ @Column(name="ACE_ORDER")
+ private Integer aceOrder;
+
+ @ManyToOne
+ @JoinColumn(name="SID")
+ private AclSid sid;
+
+ @Column(name="MASK")
+ private Integer mask;
+
+ @Column(name="GRANTING")
+ private Boolean granting;
+
+ @Column(name="AUDIT_SUCCESS")
+ private Boolean auditSuccess;
+
+ @Column(name="AUDIT_FAILURE")
+ private Boolean auditFailure;
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public AclObjectIdentity getAclObjectIdentity() {
+ return aclObjectIdentity;
+ }
+
+ public void setAclObjectIdentity(AclObjectIdentity aclObjectIdentity) {
+ this.aclObjectIdentity = aclObjectIdentity;
+ }
+
+ public Integer getAceOrder() {
+ return aceOrder;
+ }
+
+ public void setAceOrder(Integer aceOrder) {
+ this.aceOrder = aceOrder;
+ }
+
+ public AclSid getSid() {
+ return sid;
+ }
+
+ public void setSid(AclSid sid) {
+ this.sid = sid;
+ }
+
+ public Integer getMask() {
+ return mask;
+ }
+
+ public void setMask(Integer mask) {
+ this.mask = mask;
+ }
+
+ public Boolean getGranting() {
+ return granting;
+ }
+
+ public void setGranting(Boolean granting) {
+ this.granting = granting;
+ }
+
+ public Boolean getAuditSuccess() {
+ return auditSuccess;
+ }
+
+ public void setAuditSuccess(Boolean auditSuccess) {
+ this.auditSuccess = auditSuccess;
+ }
+
+ public Boolean getAuditFailure() {
+ return auditFailure;
+ }
+
+ public void setAuditFailure(Boolean auditFailure) {
+ this.auditFailure = auditFailure;
+ }
+
+}
diff --git a/src/main/java/org/springframework/security/samples/contacts/entity/AclObjectIdentity.java b/src/main/java/org/springframework/security/samples/contacts/entity/AclObjectIdentity.java
new file mode 100644
index 0000000..50f248a
--- /dev/null
+++ b/src/main/java/org/springframework/security/samples/contacts/entity/AclObjectIdentity.java
@@ -0,0 +1,133 @@
+package org.springframework.security.samples.contacts.entity;
+
+import java.io.Serializable;
+import java.util.Arrays;
+import java.util.List;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.OneToMany;
+import javax.persistence.Table;
+
+import org.springframework.security.acls.model.AccessControlEntry;
+import org.springframework.security.acls.model.Acl;
+import org.springframework.security.acls.model.MutableAcl;
+import org.springframework.security.acls.model.NotFoundException;
+import org.springframework.security.acls.model.ObjectIdentity;
+import org.springframework.security.acls.model.Permission;
+import org.springframework.security.acls.model.Sid;
+import org.springframework.security.acls.model.UnloadedSidException;
+
+@Entity
+@Table(name="ACL_OBJECT_IDENTITY")
+public class AclObjectIdentity implements ObjectIdentity{
+ @Id
+ @GeneratedValue(strategy = GenerationType.AUTO)
+ private Long id;
+
+ @ManyToOne
+ @JoinColumn(name="OBJECT_ID_CLASS")
+ private AclClass objIdClass;
+
+ @Column(name="OBJECT_ID_IDENTITY")
+ private Long objIdIdentity;
+
+ @ManyToOne
+ @JoinColumn(name="PARENT_OBJECT")
+ private AclObjectIdentity parentObject;
+
+ @ManyToOne
+ @JoinColumn(name="OWNER_SID")
+ private AclSid owner;
+
+ @Column(name="ENTRIES_INHERITING")
+ private Boolean entriesInheriting;
+
+ @OneToMany(mappedBy="aclObjectIdentity")
+ private List aclEntries;
+
+ public List getAclEntries() {
+ return aclEntries;
+ }
+
+ public void setAclEntries(List aclEntries) {
+ this.aclEntries = aclEntries;
+ }
+
+ public List getEntries() {
+ if(aclEntries!=null) {
+ return Arrays.asList(aclEntries.toArray(new AccessControlEntry[0]));
+ }
+ return null;
+ }
+
+ public void setEntries(List entries) {
+ this.aclEntries = entries;
+ }
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public AclClass getObjIdClass() {
+ return objIdClass;
+ }
+
+ public void setObjIdClass(AclClass objIdClass) {
+ this.objIdClass = objIdClass;
+ }
+
+ public Long getObjIdIdentity() {
+ return objIdIdentity;
+ }
+
+ public void setObjIdIdentity(Long objIdIdentity) {
+ this.objIdIdentity = objIdIdentity;
+ }
+
+ public AclObjectIdentity getParentObject() {
+ return parentObject;
+ }
+
+ public void setParentObject(AclObjectIdentity parentObject) {
+ this.parentObject = parentObject;
+ }
+
+ public AclSid getOwner() {
+ return owner;
+ }
+
+ public void setOwner(AclSid owner) {
+ this.owner = owner;
+ }
+
+ public Boolean getEntriesInheriting() {
+ return entriesInheriting;
+ }
+
+ public void setEntriesInheriting(Boolean entriesInheriting) {
+ this.entriesInheriting = entriesInheriting;
+ }
+
+ @Override
+ public Serializable getIdentifier() {
+
+ return this.objIdIdentity;
+ }
+
+ @Override
+ public String getType() {
+
+ return objIdClass.getClazz();
+ }
+
+}
diff --git a/src/main/java/org/springframework/security/samples/contacts/entity/AclSid.java b/src/main/java/org/springframework/security/samples/contacts/entity/AclSid.java
new file mode 100644
index 0000000..af744f7
--- /dev/null
+++ b/src/main/java/org/springframework/security/samples/contacts/entity/AclSid.java
@@ -0,0 +1,49 @@
+package org.springframework.security.samples.contacts.entity;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.Table;
+
+import org.springframework.security.acls.model.Sid;
+
+@Entity
+@Table(name="ACL_SID")
+public class AclSid implements Sid{
+ @Id
+ @GeneratedValue(strategy = GenerationType.AUTO)
+ private Long id;
+
+ @Column
+ private Boolean principal;
+
+ @Column(name="SID")
+ private String sid;
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public Boolean getPrincipal() {
+ return principal;
+ }
+
+ public void setPrincipal(Boolean principal) {
+ this.principal = principal;
+ }
+
+ public String getSid() {
+ return sid;
+ }
+
+ public void setSid(String sid) {
+ this.sid = sid;
+ }
+
+}
diff --git a/src/main/java/org/springframework/security/samples/contacts/entity/Contact.java b/src/main/java/org/springframework/security/samples/contacts/entity/Contact.java
new file mode 100644
index 0000000..d2f347d
--- /dev/null
+++ b/src/main/java/org/springframework/security/samples/contacts/entity/Contact.java
@@ -0,0 +1,71 @@
+/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.security.samples.contacts.entity;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.Table;
+
+
+/**
+ * Represents a contact.
+ *
+ * @author Ben Alex
+ */
+@Entity
+@Table(name="CONTACTS")
+public class Contact {
+ //~ Instance fields ================================================================================================
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.AUTO)
+ private Long id;
+
+ @Column
+ private String email;
+
+ @Column(name="CONTACT_NAME")
+ private String name;
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public String getEmail() {
+ return email;
+ }
+
+ public void setEmail(String email) {
+ this.email = email;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+
+}
diff --git a/src/main/java/org/springframework/security/samples/contacts/entity/Role.java b/src/main/java/org/springframework/security/samples/contacts/entity/Role.java
new file mode 100644
index 0000000..0e6c735
--- /dev/null
+++ b/src/main/java/org/springframework/security/samples/contacts/entity/Role.java
@@ -0,0 +1,33 @@
+package org.springframework.security.samples.contacts.entity;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+
+@Entity
+public class Role {
+ @Id
+ @GeneratedValue(strategy = GenerationType.AUTO)
+ private Long id;
+
+ @Column(unique=true)
+ private String name;
+
+ 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;
+ }
+}
diff --git a/src/main/java/org/springframework/security/samples/contacts/entity/User.java b/src/main/java/org/springframework/security/samples/contacts/entity/User.java
new file mode 100644
index 0000000..95f9cf4
--- /dev/null
+++ b/src/main/java/org/springframework/security/samples/contacts/entity/User.java
@@ -0,0 +1,75 @@
+package org.springframework.security.samples.contacts.entity;
+
+import java.util.List;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinTable;
+import javax.persistence.ManyToMany;
+import javax.persistence.Table;
+
+@Entity
+@Table(name="USERS")
+public class User {
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.AUTO)
+ private Long id;
+
+ @Column(unique=true)
+ private String username;
+
+ @Column
+ private String password;
+
+ @Column
+ private boolean enabled;
+
+ @ManyToMany(fetch=FetchType.EAGER)
+ @JoinTable(name="USER_ROLES")
+ private List roles;
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public String getUsername() {
+ return username;
+ }
+
+ public void setUsername(String username) {
+ this.username = username;
+ }
+
+ public String getPassword() {
+ return password;
+ }
+
+ public void setPassword(String password) {
+ this.password = password;
+ }
+
+ public boolean isEnabled() {
+ return enabled;
+ }
+
+ public void setEnabled(boolean enabled) {
+ this.enabled = enabled;
+ }
+
+ public List getRoles() {
+ return roles;
+ }
+
+ public void setRoles(List roles) {
+ this.roles = roles;
+ }
+}
diff --git a/src/main/java/org/springframework/security/samples/contacts/entity/UserPermission.java b/src/main/java/org/springframework/security/samples/contacts/entity/UserPermission.java
new file mode 100644
index 0000000..db82f82
--- /dev/null
+++ b/src/main/java/org/springframework/security/samples/contacts/entity/UserPermission.java
@@ -0,0 +1,12 @@
+package org.springframework.security.samples.contacts.entity;
+
+import org.springframework.security.acls.domain.AbstractPermission;
+
+public class UserPermission extends AbstractPermission {
+
+ protected UserPermission(int mask) {
+ super(mask);
+ // TODO Auto-generated constructor stub
+ }
+
+}
diff --git a/src/main/java/org/springframework/security/samples/contacts/service/ContactManager.java b/src/main/java/org/springframework/security/samples/contacts/service/ContactManager.java
new file mode 100644
index 0000000..14cc756
--- /dev/null
+++ b/src/main/java/org/springframework/security/samples/contacts/service/ContactManager.java
@@ -0,0 +1,58 @@
+/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.springframework.security.samples.contacts.service;
+
+import java.util.List;
+
+import org.springframework.security.access.prepost.PostFilter;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.security.acls.model.Permission;
+import org.springframework.security.acls.model.Sid;
+import org.springframework.security.samples.contacts.entity.Contact;
+
+
+/**
+ * Interface for the application's services layer.
+ *
+ * @author Ben Alex
+ */
+public interface ContactManager {
+ //~ Methods ========================================================================================================
+ @PreAuthorize("hasPermission(#contact, admin)")
+ public void addPermission(Contact contact, Sid recipient, Permission permission);
+
+ @PreAuthorize("hasPermission(#contact, admin)")
+ public void deletePermission(Contact contact, Sid recipient, Permission permission);
+
+ @PreAuthorize("hasRole('ROLE_USER')")
+ public void create(Contact contact);
+
+ @PreAuthorize("hasPermission(#contact, 'delete') or hasPermission(#contact, admin)")
+ public void delete(Contact contact);
+
+ @PreAuthorize("hasRole('ROLE_USER')")
+ // @PostFilter("hasPermission(filterObject, 'read') or hasPermission(filterObject, admin)")
+ public List getAll();
+
+ @PreAuthorize("hasRole('ROLE_USER')")
+ public List getAllRecipients();
+
+// @PreAuthorize(
+// "hasPermission(#id, 'org.springframework.security.samples.contacts.entity.Contact', read) or " +
+// "hasPermission(#id, 'org.springframework.security.samples.contacts.entity.Contact', admin)")
+ public Contact getById(Long id);
+
+ public Contact getRandomContact();
+}
diff --git a/src/main/java/org/springframework/security/samples/contacts/service/impl/ContactManagerBackend.java b/src/main/java/org/springframework/security/samples/contacts/service/impl/ContactManagerBackend.java
new file mode 100644
index 0000000..49ab4ce
--- /dev/null
+++ b/src/main/java/org/springframework/security/samples/contacts/service/impl/ContactManagerBackend.java
@@ -0,0 +1,184 @@
+/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.springframework.security.samples.contacts.service.impl;
+
+
+import java.util.List;
+import java.util.Random;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.acls.domain.BasePermission;
+import org.springframework.security.acls.domain.ObjectIdentityImpl;
+import org.springframework.security.acls.domain.PrincipalSid;
+import org.springframework.security.acls.model.AccessControlEntry;
+import org.springframework.security.acls.model.MutableAcl;
+import org.springframework.security.acls.model.MutableAclService;
+import org.springframework.security.acls.model.NotFoundException;
+import org.springframework.security.acls.model.ObjectIdentity;
+import org.springframework.security.acls.model.Permission;
+import org.springframework.security.acls.model.Sid;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.security.samples.contacts.dao.ContactDao;
+import org.springframework.security.samples.contacts.entity.Contact;
+import org.springframework.security.samples.contacts.service.ContactManager;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+
+/**
+ * Concrete implementation of {@link ContactManager}.
+ *
+ * @author Ben Alex
+ */
+
+public class ContactManagerBackend implements ContactManager {
+ //~ Instance fields ================================================================================================
+
+
+ private ContactDao contactDao;
+
+
+ private MutableAclService mutableAclService;
+ private int counter = 1000;
+
+ private static final Logger logger = LoggerFactory.getLogger(ContactManagerBackend.class);
+
+
+ public void addPermission(Contact contact, Sid recipient, Permission permission) {
+ MutableAcl acl;
+ ObjectIdentity oid = new ObjectIdentityImpl(Contact.class, contact.getId());
+
+ try {
+ acl = (MutableAcl) mutableAclService.readAclById(oid);
+ } catch (NotFoundException nfe) {
+ acl = mutableAclService.createAcl(oid);
+ }
+
+ acl.insertAce(acl.getEntries().size(), permission, recipient, true);
+ mutableAclService.updateAcl(acl);
+
+ logger.debug("Added permission " + permission + " for Sid " + recipient + " contact " + contact);
+ }
+
+ public void create(Contact contact) {
+ // Create the Contact itself
+ contact.setId(new Long(counter++));
+ contactDao.create(contact);
+
+ // Grant the current principal administrative permission to the contact
+ addPermission(contact, new PrincipalSid(getUsername()), BasePermission.ADMINISTRATION);
+
+ if (logger.isDebugEnabled()) {
+ logger.debug("Created contact " + contact + " and granted admin permission to recipient " + getUsername());
+ }
+ }
+
+ public void delete(Contact contact) {
+ contactDao.delete(contact.getId());
+
+ // Delete the ACL information as well
+ ObjectIdentity oid = new ObjectIdentityImpl(Contact.class, contact.getId());
+ mutableAclService.deleteAcl(oid, false);
+
+ if (logger.isDebugEnabled()) {
+ logger.debug("Deleted contact " + contact + " including ACL permissions");
+ }
+ }
+
+ public void deletePermission(Contact contact, Sid recipient, Permission permission) {
+ ObjectIdentity oid = new ObjectIdentityImpl(Contact.class, contact.getId());
+ MutableAcl acl = (MutableAcl) mutableAclService.readAclById(oid);
+
+ // Remove all permissions associated with this particular recipient (string equality to KISS)
+ List entries = acl.getEntries();
+
+ for (int i = 0; i < entries.size(); i++) {
+ if (entries.get(i).getSid().equals(recipient) && entries.get(i).getPermission().equals(permission)) {
+ acl.deleteAce(i);
+ }
+ }
+
+ mutableAclService.updateAcl(acl);
+
+ if (logger.isDebugEnabled()) {
+ logger.debug("Deleted contact " + contact + " ACL permissions for recipient " + recipient);
+ }
+ }
+
+ @Transactional(readOnly=true)
+ public List getAll() {
+ logger.debug("Returning all contacts");
+
+ return contactDao.findAll();
+ }
+
+ @Transactional(readOnly=true)
+ public List getAllRecipients() {
+ logger.debug("Returning all recipients");
+
+ return contactDao.findAllPrincipals();
+ }
+
+ @Transactional(readOnly=true)
+ public Contact getById(Long id) {
+ if (logger.isDebugEnabled()) {
+ logger.debug("Returning contact with id: " + id);
+ }
+
+ return contactDao.getById(id);
+ }
+
+ /**
+ * This is a public method.
+ */
+ @Transactional(readOnly=true)
+ public Contact getRandomContact() {
+ logger.debug("Returning random contact");
+
+ Random rnd = new Random();
+ List contacts = contactDao.findAll();
+ int getNumber = rnd.nextInt(contacts.size());
+
+ return contacts.get(getNumber);
+ }
+
+ protected String getUsername() {
+ Authentication auth = SecurityContextHolder.getContext().getAuthentication();
+
+ if (auth.getPrincipal() instanceof UserDetails) {
+ return ((UserDetails) auth.getPrincipal()).getUsername();
+ } else {
+ return auth.getPrincipal().toString();
+ }
+ }
+
+ public void setContactDao(ContactDao contactDao) {
+ this.contactDao = contactDao;
+ }
+
+ public void setMutableAclService(MutableAclService mutableAclService) {
+ this.mutableAclService = mutableAclService;
+ }
+
+ public void update(Contact contact) {
+ contactDao.update(contact);
+
+ logger.debug("Updated contact " + contact);
+ }
+}
diff --git a/src/main/java/org/springframework/security/samples/contacts/service/impl/ContactManagerService.java b/src/main/java/org/springframework/security/samples/contacts/service/impl/ContactManagerService.java
new file mode 100644
index 0000000..d17b383
--- /dev/null
+++ b/src/main/java/org/springframework/security/samples/contacts/service/impl/ContactManagerService.java
@@ -0,0 +1,99 @@
+package org.springframework.security.samples.contacts.service.impl;
+
+import java.util.List;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.security.acls.domain.AclImpl;
+import org.springframework.security.acls.domain.BasePermission;
+import org.springframework.security.acls.domain.ObjectIdentityImpl;
+import org.springframework.security.acls.domain.PrincipalSid;
+import org.springframework.security.acls.model.MutableAclService;
+import org.springframework.security.acls.model.ObjectIdentity;
+import org.springframework.security.acls.model.Permission;
+import org.springframework.security.acls.model.Sid;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.samples.contacts.dao.ContactDao;
+import org.springframework.security.samples.contacts.entity.Contact;
+import org.springframework.security.samples.contacts.service.ContactManager;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+@Service
+public class ContactManagerService implements ContactManager {
+
+ @Autowired
+ private ContactDao contactDao;
+
+ @Autowired
+ private MutableAclService mutableAclService;
+
+ @Override
+ @PreAuthorize("hasPermission(#contact, admin)")
+ public void addPermission(Contact contact, Sid recipient, Permission permission) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ @PreAuthorize("hasPermission(#contact, admin)")
+ public void deletePermission(Contact contact, Sid recipient, Permission permission) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ @PreAuthorize("hasRole('ROLE_USER')")
+ @Transactional
+ public void create(Contact contact) {
+ // TODO Auto-generated method stub
+ contact = contactDao.create(contact);
+
+ // Create acl_object_identity rows (and also acl_class rows as needed
+
+ final ObjectIdentity objectIdentity = new ObjectIdentityImpl(Contact.class, contact.getId());
+ mutableAclService.createAcl(objectIdentity);
+
+ AclImpl acl = (AclImpl) mutableAclService.readAclById(new ObjectIdentityImpl(Contact.class,
+ contact.getId()));
+ acl.insertAce(acl.getEntries().size(), BasePermission.ADMINISTRATION, new PrincipalSid(SecurityContextHolder.getContext().getAuthentication().getName()), true);
+
+ mutableAclService.updateAcl(acl);
+
+ }
+
+ @Override
+ @PreAuthorize("hasPermission(#contact, 'delete') or hasPermission(#contact, admin)")
+ public void delete(Contact contact) {
+ // TODO Auto-generated method stub
+ contactDao.delete(contact.getId());
+ }
+
+ @Override
+ @PreAuthorize("hasRole('ROLE_USER')")
+// @PostFilter("hasPermission(filterObject, 'read') or hasPermission(filterObject, admin)")
+ public List getAll() {
+
+ return contactDao.findAll();
+ }
+
+ @Override
+ @PreAuthorize("hasRole('ROLE_USER')")
+ public List getAllRecipients() {
+ return contactDao.findAllPrincipals();
+ }
+
+ @Override
+// @PreAuthorize("hasPermission(#id, 'org.springframework.security.samples.contacts.entity.Contact', read) or hasPermission(#id, 'org.springframework.security.samples.contacts.entity.Contact', admin)")
+ public Contact getById(Long id) {
+ // TODO Auto-generated method stub
+ return contactDao.getById(id);
+ }
+
+ @Override
+ public Contact getRandomContact() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+}
diff --git a/src/main/java/org/springframework/security/samples/contacts/service/impl/CustomUserDetailsService.java b/src/main/java/org/springframework/security/samples/contacts/service/impl/CustomUserDetailsService.java
new file mode 100644
index 0000000..9dfc61f
--- /dev/null
+++ b/src/main/java/org/springframework/security/samples/contacts/service/impl/CustomUserDetailsService.java
@@ -0,0 +1,71 @@
+package org.springframework.security.samples.contacts.service.impl;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.authority.SimpleGrantedAuthority;
+import org.springframework.security.core.userdetails.User;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.security.core.userdetails.UserDetailsService;
+import org.springframework.security.core.userdetails.UsernameNotFoundException;
+import org.springframework.security.samples.contacts.dao.UserDao;
+import org.springframework.security.samples.contacts.entity.Role;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+/**
+ * A custom {@link UserDetailsService} where user information
+ * is retrieved from a JPA repository
+ */
+@Service
+@Transactional(readOnly = true)
+public class CustomUserDetailsService implements UserDetailsService {
+
+ @Autowired
+ private UserDao userRepository;
+
+ /**
+ * Returns a populated {@link UserDetails} object.
+ * The username is first retrieved from the database and then mapped to
+ * a {@link UserDetails} object.
+ */
+ public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
+ try {
+ org.springframework.security.samples.contacts.entity.User domainUser = userRepository.findByUsername(username);
+
+ boolean enabled = true;
+ boolean accountNonExpired = true;
+ boolean credentialsNonExpired = true;
+ boolean accountNonLocked = true;
+
+ return new User(
+ domainUser.getUsername(),
+ domainUser.getPassword(),
+ domainUser.isEnabled(),
+ accountNonExpired,
+ credentialsNonExpired,
+ accountNonLocked,
+ getGrantedAuthorities(domainUser.getRoles()));
+
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+
+
+ /**
+ * Wraps {@link String} roles to {@link SimpleGrantedAuthority} objects
+ * @param roles {@link String} of roles
+ * @return list of granted authorities
+ */
+ public static List getGrantedAuthorities(List roles) {
+ List authorities = new ArrayList();
+ for (Role role : roles) {
+ authorities.add(new SimpleGrantedAuthority(role.getName()));
+ }
+ return authorities;
+ }
+}
diff --git a/src/main/java/org/springframework/security/samples/contacts/service/impl/JpaMutableAclService.java b/src/main/java/org/springframework/security/samples/contacts/service/impl/JpaMutableAclService.java
new file mode 100644
index 0000000..6dd3f26
--- /dev/null
+++ b/src/main/java/org/springframework/security/samples/contacts/service/impl/JpaMutableAclService.java
@@ -0,0 +1,362 @@
+package org.springframework.security.samples.contacts.service.impl;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+
+import javax.persistence.NoResultException;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.acls.domain.AccessControlEntryImpl;
+import org.springframework.security.acls.domain.AclImpl;
+import org.springframework.security.acls.domain.GrantedAuthoritySid;
+import org.springframework.security.acls.domain.ObjectIdentityImpl;
+import org.springframework.security.acls.domain.PrincipalSid;
+import org.springframework.security.acls.jdbc.LookupStrategy;
+import org.springframework.security.acls.model.Acl;
+import org.springframework.security.acls.model.AclCache;
+import org.springframework.security.acls.model.AlreadyExistsException;
+import org.springframework.security.acls.model.ChildrenExistException;
+import org.springframework.security.acls.model.MutableAcl;
+import org.springframework.security.acls.model.MutableAclService;
+import org.springframework.security.acls.model.NotFoundException;
+import org.springframework.security.acls.model.ObjectIdentity;
+import org.springframework.security.acls.model.Sid;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.samples.contacts.dao.AclDao;
+import org.springframework.security.samples.contacts.entity.AclClass;
+import org.springframework.security.samples.contacts.entity.AclEntry;
+import org.springframework.security.samples.contacts.entity.AclObjectIdentity;
+import org.springframework.security.samples.contacts.entity.AclSid;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.support.TransactionSynchronizationManager;
+import org.springframework.util.Assert;
+
+@Service("aclService")
+public class JpaMutableAclService implements MutableAclService {
+ private boolean foreignKeysInDatabase = true;
+
+
+ @Autowired
+ private LookupStrategy lookupStrategy;
+
+ @Autowired
+ private AclCache aclCache;
+
+ @Autowired
+ private AclDao aclDao;
+
+ @Override
+ public List findChildren(ObjectIdentity parentIdentity) {
+
+ List objects = aclDao.findChildren(parentIdentity.getIdentifier(), parentIdentity.getType());
+
+ if (objects.size() == 0) {
+ return null;
+ }
+
+ return objects;
+ }
+
+ @Override
+ public Acl readAclById(ObjectIdentity object) throws NotFoundException {
+ return readAclById(object, null);
+ }
+
+ @Override
+ public Acl readAclById(ObjectIdentity object, List sids) throws NotFoundException {
+ Map map = readAclsById(Arrays.asList(object), sids);
+ Assert.isTrue(map.containsKey(object), "There should have been an Acl entry for ObjectIdentity " + object);
+
+ return (Acl) map.get(object);
+ }
+
+ @Override
+ public Map readAclsById(List objects) throws NotFoundException {
+ return readAclsById(objects, null);
+ }
+
+ @Override
+ public Map readAclsById(List objects, List sids) throws NotFoundException {
+ Map result = lookupStrategy.readAclsById(objects, sids);
+
+ // Check every requested object identity was found (throw NotFoundException if needed)
+ for (ObjectIdentity oid : objects) {
+ if (!result.containsKey(oid)) {
+ throw new NotFoundException("Unable to find ACL information for object identity '" + oid + "'");
+ }
+ }
+
+ return result;
+ }
+
+ @Override
+ public MutableAcl createAcl(ObjectIdentity objectIdentity) throws AlreadyExistsException {
+ Assert.notNull(objectIdentity, "Object Identity required");
+
+ // Check this object identity hasn't already been persisted
+ if (retrieveObjectIdentityPrimaryKey(objectIdentity) != null) {
+ throw new AlreadyExistsException("Object identity '" + objectIdentity + "' already exists");
+ }
+
+ // Need to retrieve the current principal, in order to know who "owns" this ACL (can be changed later on)
+ Authentication auth = SecurityContextHolder.getContext().getAuthentication();
+ PrincipalSid sid = new PrincipalSid(auth);
+
+ // Create the acl_object_identity row
+ createObjectIdentity(objectIdentity, sid);
+
+ // Retrieve the ACL via superclass (ensures cache registration, proper retrieval etc)
+ Acl acl = readAclById(objectIdentity);
+ Assert.isInstanceOf(MutableAcl.class, acl, "MutableAcl should be been returned");
+
+ return (MutableAcl) acl;
+ }
+
+ /**
+ * Retrieves the primary key from the acl_object_identity table for the passed ObjectIdentity. Unlike some
+ * other methods in this implementation, this method will NOT create a row (use {@link
+ * #createObjectIdentity(ObjectIdentity, Sid)} instead).
+ *
+ * @param oid to find
+ *
+ * @return the object identity or null if not found
+ */
+ protected AclObjectIdentity retrieveObjectIdentityPrimaryKey(ObjectIdentity oid) {
+ try {
+ return aclDao.getObjectIdentity(oid.getType(), oid.getIdentifier());
+ } catch (NoResultException notFound) {
+ return null;
+ }
+ }
+
+ /**
+ * Creates an entry in the acl_object_identity table for the passed ObjectIdentity. The Sid is also
+ * necessary, as acl_object_identity has defined the sid column as non-null.
+ *
+ * @param object to represent an acl_object_identity for
+ * @param owner for the SID column (will be created if there is no acl_sid entry for this particular Sid already)
+ * @return
+ */
+ protected void createObjectIdentity(ObjectIdentity object, Sid owner) {
+ AclSid sid = createOrRetrieveSidPrimaryKey(owner, true);
+ AclClass clazz = createOrRetrieveClassPrimaryKey(object.getType(), true);
+ AclObjectIdentity identity = new AclObjectIdentity();
+ identity.setObjIdClass(clazz);
+ identity.setObjIdIdentity((Long) object.getIdentifier());
+ identity.setOwner(sid);
+ identity.setEntriesInheriting(Boolean.TRUE);
+ aclDao.createObjectIdentity(identity);
+
+ }
+
+ /**
+ * Retrieves the primary key from acl_sid, creating a new row if needed and the allowCreate property is
+ * true.
+ *
+ * @param sid to find or create
+ * @param allowCreate true if creation is permitted if not found
+ *
+ * @return the primary key or null if not found
+ *
+ * @throws IllegalArgumentException if the Sid is not a recognized implementation.
+ */
+ protected AclSid createOrRetrieveSidPrimaryKey(Sid sid, boolean allowCreate) {
+ Assert.notNull(sid, "Sid required");
+
+ String sidName;
+ boolean sidIsPrincipal = true;
+
+ if (sid instanceof PrincipalSid) {
+ sidName = ((PrincipalSid) sid).getPrincipal();
+ } else if (sid instanceof GrantedAuthoritySid) {
+ sidName = ((GrantedAuthoritySid) sid).getGrantedAuthority();
+ sidIsPrincipal = false;
+ } else {
+ throw new IllegalArgumentException("Unsupported implementation of Sid");
+ }
+
+ List sidIds = aclDao.findAclSidList(Boolean.valueOf(sidIsPrincipal), sidName);
+
+ if (!sidIds.isEmpty()) {
+ return sidIds.get(0);
+ }
+
+ if (allowCreate) {
+ AclSid sid2 = new AclSid();
+ sid2.setSid(sidName);
+ sid2.setPrincipal(Boolean.valueOf(sidIsPrincipal));
+ return aclDao.createAclSid(sid2);
+ }
+
+ return null;
+ }
+
+ /**
+ * Retrieves the primary key from {@code acl_class}, creating a new row if needed and the
+ * {@code allowCreate} property is {@code true}.
+ *
+ * @param type to find or create an entry for (often the fully-qualified class name)
+ * @param allowCreate true if creation is permitted if not found
+ *
+ * @return the primary key or null if not found
+ */
+ protected AclClass createOrRetrieveClassPrimaryKey(String type, boolean allowCreate) {
+ List classIds = aclDao.findAclClassList(type);
+
+ if (!classIds.isEmpty()) {
+ return classIds.get(0);
+ }
+
+ if (allowCreate) {
+ AclClass clazz = new AclClass();
+ clazz.setClazz(type);
+
+ Assert.isTrue(TransactionSynchronizationManager.isSynchronizationActive(),
+ "Transaction must be running");
+ return aclDao.createAclClass(clazz);
+ }
+
+ return null;
+ }
+
+
+ @Override
+ public void deleteAcl(ObjectIdentity objectIdentity, boolean deleteChildren) throws ChildrenExistException {
+ Assert.notNull(objectIdentity, "Object Identity required");
+ Assert.notNull(objectIdentity.getIdentifier(), "Object Identity doesn't provide an identifier");
+
+ if (deleteChildren) {
+ List children = findChildren(objectIdentity);
+ if (children != null) {
+ for (ObjectIdentity child : children) {
+ deleteAcl(child, true);
+ }
+ }
+ } else {
+ if (!foreignKeysInDatabase) {
+ // We need to perform a manual verification for what a FK would normally do
+ // We generally don't do this, in the interests of deadlock management
+ List children = findChildren(objectIdentity);
+ if (children != null) {
+ throw new ChildrenExistException("Cannot delete '" + objectIdentity + "' (has " + children.size()
+ + " children)");
+ }
+ }
+ }
+
+ AclObjectIdentity oidPrimaryKey = retrieveObjectIdentityPrimaryKey(objectIdentity);
+
+ // Delete this ACL's ACEs in the acl_entry table
+ aclDao.deleteEntries(oidPrimaryKey);
+
+ // Delete this ACL's acl_object_identity row
+ aclDao.deleteObjectIdentity(oidPrimaryKey);
+
+ // Clear the cache
+ aclCache.evictFromCache(objectIdentity);
+ }
+
+ @Override
+ /**
+ * This implementation will simply delete all ACEs in the database and recreate them on each invocation of
+ * this method. A more comprehensive implementation might use dirty state checking, or more likely use ORM
+ * capabilities for create, update and delete operations of {@link MutableAcl}.
+ */
+ public MutableAcl updateAcl(MutableAcl acl) throws NotFoundException {
+ Assert.notNull(acl.getId(), "Object Identity doesn't provide an identifier");
+
+ // Delete this ACL's ACEs in the acl_entry table
+ aclDao.deleteEntries(retrieveObjectIdentityPrimaryKey(acl.getObjectIdentity()));
+
+ // Create this ACL's ACEs in the acl_entry table
+ createEntries(acl);
+
+ // Change the mutable columns in acl_object_identity
+ updateObjectIdentity(acl);
+
+ // Clear the cache, including children
+ clearCacheIncludingChildren(acl.getObjectIdentity());
+
+ // Retrieve the ACL via superclass (ensures cache registration, proper retrieval etc)
+ return (MutableAcl) readAclById(acl.getObjectIdentity());
+ }
+
+
+ /**
+ * Creates a new row in acl_entry for every ACE defined in the passed MutableAcl object.
+ *
+ * @param acl containing the ACEs to insert
+ */
+ protected void createEntries(final MutableAcl acl) {
+ if(acl.getEntries().isEmpty()) {
+ return;
+ }
+ AclImpl aclImpl = (AclImpl)acl;
+ ObjectIdentityImpl objIdentity = (ObjectIdentityImpl) aclImpl.getObjectIdentity();
+ List entries = new ArrayList();
+ for(int i=0;i children = findChildren(objectIdentity);
+ if (children != null) {
+ for (ObjectIdentity child : children) {
+ clearCacheIncludingChildren(child);
+ }
+ }
+ aclCache.evictFromCache(objectIdentity);
+ }
+}
diff --git a/src/main/java/org/springframework/security/samples/contacts/utils/DataSourcePopulator.java b/src/main/java/org/springframework/security/samples/contacts/utils/DataSourcePopulator.java
new file mode 100644
index 0000000..af5952b
--- /dev/null
+++ b/src/main/java/org/springframework/security/samples/contacts/utils/DataSourcePopulator.java
@@ -0,0 +1,315 @@
+/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.springframework.security.samples.contacts.utils;
+
+import java.util.Random;
+
+import javax.sql.DataSource;
+
+import org.springframework.beans.factory.InitializingBean;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.security.acls.domain.AclImpl;
+import org.springframework.security.acls.domain.BasePermission;
+import org.springframework.security.acls.domain.ObjectIdentityImpl;
+import org.springframework.security.acls.domain.PrincipalSid;
+import org.springframework.security.acls.model.MutableAcl;
+import org.springframework.security.acls.model.MutableAclService;
+import org.springframework.security.acls.model.ObjectIdentity;
+import org.springframework.security.acls.model.Permission;
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.authority.AuthorityUtils;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.samples.contacts.entity.Contact;
+import org.springframework.transaction.PlatformTransactionManager;
+import org.springframework.transaction.TransactionStatus;
+import org.springframework.transaction.support.TransactionCallback;
+import org.springframework.transaction.support.TransactionTemplate;
+import org.springframework.util.Assert;
+
+
+/**
+ * Populates the Contacts in-memory database with contact and ACL information.
+ *
+ * @author Ben Alex
+ */
+public class DataSourcePopulator implements InitializingBean {
+ //~ Instance fields ================================================================================================
+
+ JdbcTemplate template;
+ private MutableAclService mutableAclService;
+ final Random rnd = new Random();
+ TransactionTemplate tt;
+ final String[] firstNames = {
+ "Bob", "Mary", "James", "Jane", "Kristy", "Kirsty", "Kate", "Jeni", "Angela", "Melanie", "Kent", "William",
+ "Geoff", "Jeff", "Adrian", "Amanda", "Lisa", "Elizabeth", "Prue", "Richard", "Darin", "Phillip", "Michael",
+ "Belinda", "Samantha", "Brian", "Greg", "Matthew"
+ };
+ final String[] lastNames = {
+ "Smith", "Williams", "Jackson", "Rictor", "Nelson", "Fitzgerald", "McAlpine", "Sutherland", "Abbott", "Hall",
+ "Edwards", "Gates", "Black", "Brown", "Gray", "Marwell", "Booch", "Johnson", "McTaggart", "Parklin",
+ "Findlay", "Robinson", "Giugni", "Lang", "Chi", "Carmichael"
+ };
+ private int createEntities = 50;
+
+ //~ Methods ========================================================================================================
+ public void afterPropertiesSet() throws Exception {
+ Assert.notNull(template, "dataSource required");
+ // Set a user account that will initially own all the created data
+ Authentication authRequest = new UsernamePasswordAuthenticationToken("rod", "koala",
+ AuthorityUtils.createAuthorityList("ROLE_IGNORED"));
+ SecurityContextHolder.getContext().setAuthentication(authRequest);
+
+ template.execute("INSERT INTO USERS(ID,USERNAME,PASSWORD,ENABLED) VALUES(1,'rod','$2a$10$75pBjapg4Nl8Pzd.3JRnUe7PDJmk9qBGwNEJDAlA3V.dEJxcDKn5O',1)");
+ template.execute("INSERT INTO USERS(ID,USERNAME,PASSWORD,ENABLED) VALUES(2,'dianne','$2a$04$bCMEyxrdF/7sgfUiUJ6Ose2vh9DAMaVBldS1Bw2fhi1jgutZrr9zm',1)");
+ template.execute("INSERT INTO USERS(ID,USERNAME,PASSWORD,ENABLED) VALUES(3,'scott','$2a$06$eChwvzAu3TSexnC3ynw4LOSw1qiEbtNItNeYv5uI40w1i3paoSfLu',1)");
+ template.execute("INSERT INTO USERS(ID,USERNAME,PASSWORD,ENABLED) VALUES(4,'peter','$2a$04$8.H8bCMROLF4CIgd7IpeQ.tcBXLP5w8iplO0n.kCIkISwrIgX28Ii',0)");
+ template.execute("INSERT INTO USERS(ID,USERNAME,PASSWORD,ENABLED) VALUES(5,'bill','$2a$04$8.H8bCMROLF4CIgd7IpeQ.3khQlPVNWbp8kzSQqidQHGFurim7P8O',1)");
+ template.execute("INSERT INTO USERS(ID,USERNAME,PASSWORD,ENABLED) VALUES(6,'bob','$2a$06$zMgxlMf01SfYNcdx7n4NpeFlAGU8apCETz/i2C7VlYWu6IcNyn4Ay',1)");
+ template.execute("INSERT INTO USERS(ID,USERNAME,PASSWORD,ENABLED) VALUES(7,'jane','$2a$05$ZrdS7yMhCZ1J.AAidXZhCOxdjD8LO/dhlv4FJzkXA6xh9gdEbBT/u',1)");
+ template.execute("INSERT INTO ROLE(ID,NAME) VALUES(1,'ROLE_USER')");
+ template.execute("INSERT INTO ROLE(ID,NAME) VALUES(2,'ROLE_SUPERVISOR')");
+ template.execute("INSERT INTO USER_ROLES(USER_ID,ROLE_ID) VALUES(1,1)");
+ template.execute("INSERT INTO USER_ROLES(USER_ID,ROLE_ID) VALUES(1,2)");
+
+// template.execute("INSERT INTO contacts VALUES (1, 'John Smith', 'john@somewhere.com');");
+// template.execute("INSERT INTO contacts VALUES (2, 'Michael Citizen', 'michael@xyz.com');");
+// template.execute("INSERT INTO contacts VALUES (3, 'Joe Bloggs', 'joe@demo.com');");
+// template.execute("INSERT INTO contacts VALUES (4, 'Karen Sutherland', 'karen@sutherland.com');");
+// template.execute("INSERT INTO contacts VALUES (5, 'Mitchell Howard', 'mitchell@abcdef.com');");
+// template.execute("INSERT INTO contacts VALUES (6, 'Rose Costas', 'rose@xyz.com');");
+// template.execute("INSERT INTO contacts VALUES (7, 'Amanda Smith', 'amanda@abcdef.com');");
+// template.execute("INSERT INTO contacts VALUES (8, 'Cindy Smith', 'cindy@smith.com');");
+// template.execute("INSERT INTO contacts VALUES (9, 'Jonathan Citizen', 'jonathan@xyz.com');");
+ SecurityContextHolder.clearContext();
+ }
+ public void afterPropertiesSet2() throws Exception {
+ Assert.notNull(mutableAclService, "mutableAclService required");
+ Assert.notNull(template, "dataSource required");
+ Assert.notNull(tt, "platformTransactionManager required");
+
+ // Set a user account that will initially own all the created data
+ Authentication authRequest = new UsernamePasswordAuthenticationToken("rod", "koala",
+ AuthorityUtils.createAuthorityList("ROLE_IGNORED"));
+ SecurityContextHolder.getContext().setAuthentication(authRequest);
+
+ try {
+ template.execute("DROP TABLE CONTACTS");
+ template.execute("DROP TABLE AUTHORITIES");
+ template.execute("DROP TABLE USERS");
+ template.execute("DROP TABLE ACL_ENTRY");
+ template.execute("DROP TABLE ACL_OBJECT_IDENTITY");
+ template.execute("DROP TABLE ACL_CLASS");
+ template.execute("DROP TABLE ACL_SID");
+ } catch(Exception e) {
+ System.out.println("Failed to drop tables: " + e.getMessage());
+ }
+/**
+ template.execute(
+ "CREATE TABLE ACL_SID(" +
+ "ID BIGINT GENERATED BY DEFAULT AS IDENTITY(START WITH 100) NOT NULL PRIMARY KEY," +
+ "PRINCIPAL BOOLEAN NOT NULL," +
+ "SID VARCHAR_IGNORECASE(100) NOT NULL," +
+ "CONSTRAINT UNIQUE_UK_1 UNIQUE(SID,PRINCIPAL));");
+ template.execute(
+ "CREATE TABLE ACL_CLASS(" +
+ "ID BIGINT GENERATED BY DEFAULT AS IDENTITY(START WITH 100) NOT NULL PRIMARY KEY," +
+ "CLASS VARCHAR_IGNORECASE(100) NOT NULL," +
+ "CONSTRAINT UNIQUE_UK_2 UNIQUE(CLASS));");
+ template.execute(
+ "CREATE TABLE ACL_OBJECT_IDENTITY(" +
+ "ID BIGINT GENERATED BY DEFAULT AS IDENTITY(START WITH 100) NOT NULL PRIMARY KEY," +
+ "OBJECT_ID_CLASS BIGINT NOT NULL," +
+ "OBJECT_ID_IDENTITY BIGINT NOT NULL," +
+ "PARENT_OBJECT BIGINT," +
+ "OWNER_SID BIGINT," +
+ "ENTRIES_INHERITING BOOLEAN NOT NULL," +
+ "CONSTRAINT UNIQUE_UK_3 UNIQUE(OBJECT_ID_CLASS,OBJECT_ID_IDENTITY)," +
+ "CONSTRAINT FOREIGN_FK_1 FOREIGN KEY(PARENT_OBJECT)REFERENCES ACL_OBJECT_IDENTITY(ID)," +
+ "CONSTRAINT FOREIGN_FK_2 FOREIGN KEY(OBJECT_ID_CLASS)REFERENCES ACL_CLASS(ID)," +
+ "CONSTRAINT FOREIGN_FK_3 FOREIGN KEY(OWNER_SID)REFERENCES ACL_SID(ID));");
+ template.execute(
+ "CREATE TABLE ACL_ENTRY(" +
+ "ID BIGINT GENERATED BY DEFAULT AS IDENTITY(START WITH 100) NOT NULL PRIMARY KEY," +
+ "ACL_OBJECT_IDENTITY BIGINT NOT NULL,ACE_ORDER INT NOT NULL,SID BIGINT NOT NULL," +
+ "MASK INTEGER NOT NULL,GRANTING BOOLEAN NOT NULL,AUDIT_SUCCESS BOOLEAN NOT NULL," +
+ "AUDIT_FAILURE BOOLEAN NOT NULL,CONSTRAINT UNIQUE_UK_4 UNIQUE(ACL_OBJECT_IDENTITY,ACE_ORDER)," +
+ "CONSTRAINT FOREIGN_FK_4 FOREIGN KEY(ACL_OBJECT_IDENTITY) REFERENCES ACL_OBJECT_IDENTITY(ID)," +
+ "CONSTRAINT FOREIGN_FK_5 FOREIGN KEY(SID) REFERENCES ACL_SID(ID));");
+
+ template.execute(
+ "CREATE TABLE USERS(USERNAME VARCHAR_IGNORECASE(50) NOT NULL PRIMARY KEY,PASSWORD VARCHAR_IGNORECASE(500) NOT NULL,ENABLED BOOLEAN NOT NULL);");
+ template.execute(
+ "CREATE TABLE AUTHORITIES(USERNAME VARCHAR_IGNORECASE(50) NOT NULL,AUTHORITY VARCHAR_IGNORECASE(50) NOT NULL,CONSTRAINT FK_AUTHORITIES_USERS FOREIGN KEY(USERNAME) REFERENCES USERS(USERNAME));");
+ template.execute("CREATE UNIQUE INDEX IX_AUTH_USERNAME ON AUTHORITIES(USERNAME,AUTHORITY);");
+
+ template.execute(
+ "CREATE TABLE CONTACTS(ID BIGINT NOT NULL PRIMARY KEY, CONTACT_NAME VARCHAR_IGNORECASE(50) NOT NULL, EMAIL VARCHAR_IGNORECASE(50) NOT NULL)");
+*/
+ /*
+ Passwords encoded using MD5, NOT in Base64 format, with null as salt
+ Encoded password for rod is "koala"
+ Encoded password for dianne is "emu"
+ Encoded password for scott is "wombat"
+ Encoded password for peter is "opal" (but user is disabled)
+ Encoded password for bill is "wombat"
+ Encoded password for bob is "wombat"
+ Encoded password for jane is "wombat"
+
+ */
+ template.execute("INSERT INTO USERS VALUES('rod','$2a$10$75pBjapg4Nl8Pzd.3JRnUe7PDJmk9qBGwNEJDAlA3V.dEJxcDKn5O',TRUE);");
+ template.execute("INSERT INTO USERS VALUES('dianne','$2a$04$bCMEyxrdF/7sgfUiUJ6Ose2vh9DAMaVBldS1Bw2fhi1jgutZrr9zm',TRUE);");
+ template.execute("INSERT INTO USERS VALUES('scott','$2a$06$eChwvzAu3TSexnC3ynw4LOSw1qiEbtNItNeYv5uI40w1i3paoSfLu',TRUE);");
+ template.execute("INSERT INTO USERS VALUES('peter','$2a$04$8.H8bCMROLF4CIgd7IpeQ.tcBXLP5w8iplO0n.kCIkISwrIgX28Ii',FALSE);");
+ template.execute("INSERT INTO USERS VALUES('bill','$2a$04$8.H8bCMROLF4CIgd7IpeQ.3khQlPVNWbp8kzSQqidQHGFurim7P8O',TRUE);");
+ template.execute("INSERT INTO USERS VALUES('bob','$2a$06$zMgxlMf01SfYNcdx7n4NpeFlAGU8apCETz/i2C7VlYWu6IcNyn4Ay',TRUE);");
+ template.execute("INSERT INTO USERS VALUES('jane','$2a$05$ZrdS7yMhCZ1J.AAidXZhCOxdjD8LO/dhlv4FJzkXA6xh9gdEbBT/u',TRUE);");
+ template.execute("INSERT INTO AUTHORITIES VALUES('rod','ROLE_USER');");
+ template.execute("INSERT INTO AUTHORITIES VALUES('rod','ROLE_SUPERVISOR');");
+ template.execute("INSERT INTO AUTHORITIES VALUES('dianne','ROLE_USER');");
+ template.execute("INSERT INTO AUTHORITIES VALUES('scott','ROLE_USER');");
+ template.execute("INSERT INTO AUTHORITIES VALUES('peter','ROLE_USER');");
+ template.execute("INSERT INTO AUTHORITIES VALUES('bill','ROLE_USER');");
+ template.execute("INSERT INTO AUTHORITIES VALUES('bob','ROLE_USER');");
+ template.execute("INSERT INTO AUTHORITIES VALUES('jane','ROLE_USER');");
+
+ template.execute("INSERT INTO contacts VALUES (1, 'John Smith', 'john@somewhere.com');");
+ template.execute("INSERT INTO contacts VALUES (2, 'Michael Citizen', 'michael@xyz.com');");
+ template.execute("INSERT INTO contacts VALUES (3, 'Joe Bloggs', 'joe@demo.com');");
+ template.execute("INSERT INTO contacts VALUES (4, 'Karen Sutherland', 'karen@sutherland.com');");
+ template.execute("INSERT INTO contacts VALUES (5, 'Mitchell Howard', 'mitchell@abcdef.com');");
+ template.execute("INSERT INTO contacts VALUES (6, 'Rose Costas', 'rose@xyz.com');");
+ template.execute("INSERT INTO contacts VALUES (7, 'Amanda Smith', 'amanda@abcdef.com');");
+ template.execute("INSERT INTO contacts VALUES (8, 'Cindy Smith', 'cindy@smith.com');");
+ template.execute("INSERT INTO contacts VALUES (9, 'Jonathan Citizen', 'jonathan@xyz.com');");
+
+ for (int i = 10; i < createEntities; i++) {
+ String[] person = selectPerson();
+ template.execute("INSERT INTO contacts VALUES (" + i + ", '" + person[2] + "', '" + person[0].toLowerCase()
+ + "@" + person[1].toLowerCase() + ".com');");
+ }
+
+ // Create acl_object_identity rows (and also acl_class rows as needed
+ for (int i = 1; i < createEntities; i++) {
+ final ObjectIdentity objectIdentity = new ObjectIdentityImpl(Contact.class, new Long(i));
+ tt.execute(new TransactionCallback