diff --git a/pom.xml b/pom.xml
index 20b2e0c94fac0fc0066b734a30eb80790488ddbd..662d4c3ad9f84ec2444cbee8ed30ac9e6bff8e39 100644
--- a/pom.xml
+++ b/pom.xml
@@ -10,6 +10,7 @@
domain
+ service
@@ -18,6 +19,7 @@
1.8
UTF-8
UTF-8
+ false
7.0
@@ -33,11 +35,15 @@
1.0.0.Alpha7
5.1.21
1.5.10
+ 3.4
+ 1.0.0.CR4
+ 4.1
1.1.0.Alpha1
2.10
2.18.1
+ 2.7
@@ -56,6 +62,18 @@
import
+
+
+ ${project.groupId}
+ domain
+ ${project.version}
+
+
+ ${project.groupId}
+ service
+ ${project.version}
+
+
org.apache.commons
@@ -74,6 +92,11 @@
java-hamcrest
${hamcrest.version}
+
+ org.easymock
+ easymock
+ ${easymock.version}
+
org.jboss.arquillian.extension
arquillian-persistence-dbunit
@@ -110,21 +133,15 @@
${wildfly.version}
-
-
- es.uvigo.esei.dgss
- domain
- ${project.version}
+
+ org.jboss.arquillian.container
+ arquillian-glassfish-embedded-3.1
+ ${arquillian.glassfish.embedded.version}
-
- es.uvigo.esei.dgss
- service
- ${project.version}
-
-
- es.uvigo.esei.dgss
- web
- ${project.version}
+
+ org.glassfish.main.extras
+ glassfish-embedded-all
+ ${glassfish.embedded.all.version}
@@ -142,18 +159,57 @@
maven-surefire-plugin
${maven.surefire.plugin.version}
+
+ org.apache.maven.plugins
+ maven-resources-plugin
+ ${maven.resources.plugin.version}
+
org.wildfly.plugins
wildfly-maven-plugin
${wildfly.maven.plugin.version}
+
+
+ org.eclipse.m2e
+ lifecycle-mapping
+ 1.0.0
+
+
+
+
+
+
+ org.apache.maven.plugins
+
+
+ maven-dependency-plugin
+
+
+ [2.10,)
+
+
+ unpack
+
+
+
+
+
+
+
+
+
+
- wildfly-embedded-mysql
+ wildfly-embedded-h2
+
+ true
+
org.wildfly
@@ -182,7 +238,7 @@
src/test/resources
- src/test/resources-wildfly-embedded-mysql
+ src/test/resources-wildfly-embedded-h2
@@ -193,13 +249,13 @@
1
org.jboss.logmanager.LogManager
- ${project.basedir}/target/wildfly-${wildfly.version}
- ${project.basedir}/target/wildfly-${wildfly.version}/modules
- wildfly-embedded
+ ${wildfly.version}
+ wildfly-embedded-h2
false
+
org.apache.maven.plugins
maven-dependency-plugin
@@ -223,22 +279,27 @@
+
+
+
+
+ org.apache.maven.plugins
+ maven-resources-plugin
+
- copy-dependencies
+ copy-mysql-ds
process-test-classes
- copy
+ copy-resources
-
-
- mysql
- mysql-connector-java
- jar
- false
- target/wildfly-${wildfly.version}/standalone/deployments
-
-
+ target/wildfly-${wildfly.version}/standalone/configuration
+
+
+ src/test/resources-wildfly-embedded-h2
+ standalone.xml
+
+
@@ -246,8 +307,9 @@
+
- wildfly-embedded-h2
+ wildfly-embedded-mysql
org.wildfly
@@ -276,7 +338,7 @@
src/test/resources
- src/test/resources-wildfly-embedded-h2
+ src/test/resources-wildfly-embedded-mysql
@@ -287,14 +349,13 @@
1
org.jboss.logmanager.LogManager
- ${project.basedir}/target/wildfly-${wildfly.version}
- ${project.basedir}/target/wildfly-${wildfly.version}/modules
- wildfly-embedded
+ ${mysql.connector.java.version}
+ ${wildfly.version}
+ wildfly-embedded-mysql
false
-
org.apache.maven.plugins
maven-dependency-plugin
@@ -318,6 +379,54 @@
+
+ copy-dependencies
+ process-test-classes
+
+ copy
+
+
+
+
+ mysql
+ mysql-connector-java
+ ${mysql.connector.java.version}
+ jar
+ false
+ target/wildfly-${wildfly.version}/standalone/deployments
+
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-resources-plugin
+
+
+ copy-mysql-ds
+ process-test-classes
+
+ copy-resources
+
+
+ target/wildfly-${wildfly.version}/standalone
+
+
+ src/test/resources-wildfly-embedded-mysql
+ mysql-ds.xml
+ deployments
+
+
+ src/test/resources-wildfly-embedded-mysql
+ standalone.xml
+ configuration
+
+
+
+
diff --git a/service/.gitignore b/service/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..b83d22266ac8aa2f8df2edef68082c789727841d
--- /dev/null
+++ b/service/.gitignore
@@ -0,0 +1 @@
+/target/
diff --git a/service/pom.xml b/service/pom.xml
new file mode 100644
index 0000000000000000000000000000000000000000..e94ef22619df449c14a96469ae3eb0ac8f9718b6
--- /dev/null
+++ b/service/pom.xml
@@ -0,0 +1,54 @@
+
+ 4.0.0
+
+ es.uvigo.esei.xcs
+ sample
+ 0.0.1-SNAPSHOT
+
+ service
+ jar
+
+ Service
+ XCS Sample - Service
+
+
+
+
+ javax
+ javaee-api
+ provided
+
+
+ es.uvigo.esei.xcs
+ domain
+
+
+
+
+ junit
+ junit
+ test
+
+
+ org.hamcrest
+ java-hamcrest
+ test
+
+
+ org.easymock
+ easymock
+ test
+
+
+ org.jboss.arquillian.junit
+ arquillian-junit-container
+ test
+
+
+ org.jboss.arquillian.extension
+ arquillian-persistence-dbunit
+ test
+
+
+
\ No newline at end of file
diff --git a/service/src/main/java/es/uvigo/esei/xcs/service/OwnerService.java b/service/src/main/java/es/uvigo/esei/xcs/service/OwnerService.java
new file mode 100644
index 0000000000000000000000000000000000000000..b2fe2466ddf46bb9a8a01e57da1e641757b59929
--- /dev/null
+++ b/service/src/main/java/es/uvigo/esei/xcs/service/OwnerService.java
@@ -0,0 +1,124 @@
+package es.uvigo.esei.xcs.service;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.annotation.security.RolesAllowed;
+import javax.ejb.Stateless;
+import javax.persistence.EntityExistsException;
+import javax.persistence.EntityManager;
+import javax.persistence.PersistenceContext;
+
+import es.uvigo.esei.xcs.domain.entities.Owner;
+import es.uvigo.esei.xcs.domain.entities.Pet;
+
+/**
+ * EJB for the Owners. Only administrators have access to this class.
+ *
+ * @author Miguel Reboiro Jato
+ */
+@Stateless
+@RolesAllowed("ADMIN")
+public class OwnerService {
+ @PersistenceContext
+ private EntityManager em;
+
+ /**
+ * Returns the owner identified by {@code login}. If there is no owner with
+ * the specified login, {@code null} will be returned.
+ *
+ * @param login the login of an owner.
+ * @return the owner with the provided login or {@code null} if there is no
+ * owner with the specified login.
+ * @throws IllegalArgumentException if {@code login} is {@code null} or it
+ * does not identifies a valid owner.
+ */
+ public Owner get(String login) {
+ return em.find(Owner.class, login);
+ }
+
+ /**
+ * Returns the complete list of owners.
+ *
+ * @return the complete list of owners.
+ */
+ public List list() {
+ return em.createQuery("SELECT o FROM Owner o", Owner.class)
+ .getResultList();
+ }
+
+ /**
+ * Returns the list of owners that have a pet with the specified name.
+ *
+ * @param petName a pet's name.
+ * @return the list of owners that have a pet with the specified name. The
+ * list may be empty if any owner has a pet with the specified name.
+ * @throws IllegalArgumentException if {@code petName} is {@code null}.
+ */
+ public List findByPetName(String petName) {
+ if (petName == null)
+ throw new IllegalArgumentException("petName can't be null");
+
+ final String query = "SELECT o FROM Owner o JOIN o.pets p " +
+ "WHERE p.name = :petName";
+
+ return em.createQuery(query, Owner.class)
+ .setParameter("petName", petName)
+ .getResultList();
+ }
+
+ /**
+ * Creates a new owner. If the owner already has pets, they will be created
+ * too.
+ *
+ * @param owner a new owner to be stored.
+ * @return the persistent version of the owner created.
+ * @throws IllegalArgumentException if {@code owner} is {@code null}.
+ * @throws EntityExistsException if an owner with the same login already
+ * exists.
+ */
+ public Owner create(Owner owner) {
+ if (owner == null)
+ throw new IllegalArgumentException("owner can't be null");
+
+ this.em.persist(owner);
+
+ return owner;
+ }
+
+ /**
+ * Updates a new owner. If the owner is not stored, it will be persisted.
+ *
+ * @param owner an owner to be updated.
+ * @throws IllegalArgumentException if {@code owner} is {@code null}.
+ */
+ public Owner update(Owner owner) {
+ if (owner == null)
+ throw new IllegalArgumentException("owner can't be null");
+
+ return em.merge(owner);
+ }
+
+ /**
+ * Deletes an owner.
+ *
+ * @param login the login of the owner to be deleted.
+ * @throws IllegalArgumentException if {@code login} is {@code null} or if
+ * it does not identifies a valid owner.
+ */
+ public void remove(String login) {
+ em.remove(this.get(login));
+ }
+
+ /**
+ * Returns the list of pets of an owner.
+ *
+ * @param login the login of the owner that owns the pets.
+ * @return the list of pets of an owner.
+ * @throws IllegalArgumentException if {@code login} is {@code null} or it
+ * does not identifies a valid owner.
+ */
+ public List getPets(String login) {
+ return new ArrayList<>(this.get(login).getPets());
+ }
+}
diff --git a/service/src/main/java/es/uvigo/esei/xcs/service/PetService.java b/service/src/main/java/es/uvigo/esei/xcs/service/PetService.java
new file mode 100644
index 0000000000000000000000000000000000000000..f57aa2686e9fdccdb6585d33c2b7d2c077024f6e
--- /dev/null
+++ b/service/src/main/java/es/uvigo/esei/xcs/service/PetService.java
@@ -0,0 +1,121 @@
+package es.uvigo.esei.xcs.service;
+
+import java.security.Principal;
+import java.util.List;
+
+import javax.annotation.security.RolesAllowed;
+import javax.ejb.EJBAccessException;
+import javax.ejb.Stateless;
+import javax.inject.Inject;
+import javax.persistence.EntityManager;
+import javax.persistence.PersistenceContext;
+
+import es.uvigo.esei.xcs.domain.entities.Owner;
+import es.uvigo.esei.xcs.domain.entities.Pet;
+
+/**
+ * EJB for the Pets. Only owners have access to this class, and only to their
+ * own pets.
+ *
+ * @author Miguel Reboiro Jato
+ */
+@Stateless
+@RolesAllowed("OWNER")
+public class PetService {
+ @Inject
+ private Principal currentOwner;
+
+ @PersistenceContext
+ private EntityManager em;
+
+ /**
+ * Returns a pet identified by the provided id. If an owner tries to access
+ * a pet that does now own, an {@link EJBAccessException} will be thrown.
+ *
+ * @param id the identified of a pet.
+ * @return a pet identified by the provided identifier or {@code null} if no
+ * pet exists with the provided identifier.
+ * @throws EJBAccessException if the current owner does not owns the pet.
+ */
+ public Pet get(int id) {
+ final Pet pet = em.find(Pet.class, id);
+
+ if (pet == null) {
+ return null;
+ } else if (pet.getOwner().getLogin().equals(this.currentOwner.getName())) {
+ return pet;
+ } else {
+ throw new EJBAccessException("Pet's owner is not the current principal");
+ }
+ }
+
+ /**
+ * Returns the complete list of pets of the current owner.
+ *
+ * @return the complete list of pets of the current owner.
+ */
+ public List list() {
+ return em.createQuery("SELECT p FROM Pet p WHERE p.owner.login = :login", Pet.class)
+ .setParameter("login", currentOwner.getName())
+ .getResultList();
+ }
+
+ /**
+ * Creates a new pet owned by the current user.
+ *
+ * @param pet a new pet to be stored.
+ * @return the persistent version of the pet created.
+ * @throws EJBAccessException if the pet already has an owner and it is not
+ * the current user. If the pet has no owner, this exception will be never
+ * thrown.
+ * @throws IllegalArgumentException if a pet with the same identifier
+ * already exists.
+ */
+ public Pet create(Pet pet) {
+ final Owner owner = em.find(Owner.class, currentOwner.getName());
+
+ if (pet.getOwner() != null && !pet.getOwner().getLogin().equals(owner.getLogin())) {
+ throw new EJBAccessException("Pet's owner is not the current principal");
+ } else {
+ pet.setOwner(owner);
+
+ this.em.persist(pet);
+
+ return pet;
+ }
+ }
+
+ /**
+ * Updates the information of a pet. If the pet is not stored, it will be
+ * created.
+ *
+ * @param pet the pet to be updated.
+ * @throws IllegalArgumentException if the pet has no owner.
+ * @throws EJBAccessException if the pet's owner is not the current user.
+ */
+ public Pet update(Pet pet) {
+ if (pet.getOwner() == null)
+ throw new IllegalArgumentException("Pet must have an owner");
+
+ if (pet.getOwner().getLogin().equals(this.currentOwner.getName())) {
+ return em.merge(pet);
+ } else {
+ throw new EJBAccessException("Pet's owner is not the current principal");
+ }
+ }
+
+ /**
+ * Deletes a pet.
+ *
+ * @param id the identifier of the pet to be deleted.
+ * @throws IllegalArgumentException if there is no pet with the provided
+ * identifier.
+ * @throws EJBAccessException if the pet's owner is not the current user.
+ */
+ public void remove(int id) {
+ final Pet pet = this.get(id);
+ pet.setOwner(null);
+
+ em.remove(pet);
+ }
+}
diff --git a/service/src/test/java/es/uvigo/esei/xcs/domain/entities/OwnersDataset.java b/service/src/test/java/es/uvigo/esei/xcs/domain/entities/OwnersDataset.java
index 35cbd06fd2ebd5e43899459c44afe9600c1f719f..6946a5146b7850e41da40b6de309eb3905cd6e06 100644
--- a/service/src/test/java/es/uvigo/esei/xcs/domain/entities/OwnersDataset.java
+++ b/service/src/test/java/es/uvigo/esei/xcs/domain/entities/OwnersDataset.java
@@ -74,6 +74,10 @@ public class OwnersDataset {
);
}
+ public static Owner anyOwner() {
+ return ownerWithPets();
+ }
+
public static Owner ownerWithPets() {
return owners()[1];
}
@@ -82,7 +86,31 @@ public class OwnersDataset {
return owners()[3];
}
+ public static Pet anyPet() {
+ return pet(existentPetId());
+ }
+
public static Pet newPet() {
- return new Pet("Lorenacat", AnimalType.CAT, new Date(946684861000L));
+ return newPetWithOwner(null);
+ }
+
+ public static Pet newPetWithOwner(Owner owner) {
+ return new Pet("Lorenacat", AnimalType.CAT, new Date(946684861000L), owner);
+ }
+
+ public static String existentLogin() {
+ return "pepe";
+ }
+
+ public static String existentPetName() {
+ return "Pepecat";
+ }
+
+ public static int existentPetId() {
+ return 2;
+ }
+
+ public static int nonExistentPetId() {
+ return 1000000;
}
}
diff --git a/service/src/test/java/es/uvigo/esei/xcs/service/OwnerServiceIllegalAccessIntegrationTest.java b/service/src/test/java/es/uvigo/esei/xcs/service/OwnerServiceIllegalAccessIntegrationTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..a92caf1ab42c727eff655a52a9e414a08af4e592
--- /dev/null
+++ b/service/src/test/java/es/uvigo/esei/xcs/service/OwnerServiceIllegalAccessIntegrationTest.java
@@ -0,0 +1,123 @@
+package es.uvigo.esei.xcs.service;
+
+import static es.uvigo.esei.xcs.domain.entities.OwnersDataset.anyOwner;
+import static es.uvigo.esei.xcs.domain.entities.OwnersDataset.existentLogin;
+import static es.uvigo.esei.xcs.domain.entities.OwnersDataset.existentPetName;
+import static es.uvigo.esei.xcs.domain.entities.OwnersDataset.newOwnerWithoutPets;
+
+import javax.ejb.EJB;
+import javax.ejb.EJBAccessException;
+import javax.ejb.EJBTransactionRolledbackException;
+import javax.inject.Inject;
+
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.junit.Arquillian;
+import org.jboss.arquillian.persistence.CleanupUsingScript;
+import org.jboss.arquillian.persistence.ShouldMatchDataSet;
+import org.jboss.arquillian.persistence.TestExecutionPhase;
+import org.jboss.arquillian.persistence.UsingDataSet;
+import org.jboss.shrinkwrap.api.Archive;
+import org.jboss.shrinkwrap.api.ShrinkWrap;
+import org.jboss.shrinkwrap.api.asset.EmptyAsset;
+import org.jboss.shrinkwrap.api.spec.WebArchive;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import es.uvigo.esei.xcs.domain.entities.Owner;
+import es.uvigo.esei.xcs.domain.entities.OwnersDataset;
+import es.uvigo.esei.xcs.service.util.security.RoleCaller;
+
+@RunWith(Arquillian.class)
+@UsingDataSet("owners.xml")
+@ShouldMatchDataSet("owners.xml")
+@CleanupUsingScript(phase = TestExecutionPhase.BEFORE, value = { "cleanup.sql", "cleanup-autoincrement.sql" })
+public class OwnerServiceIllegalAccessIntegrationTest {
+ @Inject
+ private OwnerService facade;
+
+ @EJB(beanName = "owner-caller")
+ private RoleCaller owner;
+
+ @Deployment
+ public static Archive> createDeployment() {
+ final WebArchive archive = ShrinkWrap.create(WebArchive.class, "test.war")
+ .addClasses(OwnerService.class, OwnersDataset.class)
+ .addPackage(RoleCaller.class.getPackage())
+ .addPackage(Owner.class.getPackage())
+ .addAsResource("test-persistence.xml", "META-INF/persistence.xml")
+ .addAsWebInfResource("jboss-web.xml")
+ .addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml");
+
+ return archive;
+ }
+
+ @Test(expected = EJBAccessException.class)
+ public void testGetNoRole() {
+ facade.get(existentLogin());
+ }
+
+ @Test(expected = EJBAccessException.class)
+ public void testListNoRole() {
+ facade.list();
+ }
+
+ @Test(expected = EJBAccessException.class)
+ public void testFindByPetNameNoRole() {
+ facade.findByPetName(existentPetName());
+ }
+
+ @Test(expected = EJBAccessException.class)
+ public void testCreateNoRole() {
+ facade.create(newOwnerWithoutPets());
+ }
+
+ @Test(expected = EJBAccessException.class)
+ public void testUpdateNoRole() {
+ facade.update(anyOwner());
+ }
+
+ @Test(expected = EJBAccessException.class)
+ public void testRemoveNoRole() {
+ facade.remove(existentLogin());
+ }
+
+ @Test(expected = EJBAccessException.class)
+ public void testGetPetsNoRole() {
+ facade.getPets(existentLogin());
+ }
+
+ @Test(expected = EJBTransactionRolledbackException.class)
+ public void testGetRoleOwner() {
+ this.owner.run(this::testGetNoRole);
+ }
+
+ @Test(expected = EJBTransactionRolledbackException.class)
+ public void testListRoleOwner() {
+ this.owner.run(this::testListNoRole);
+ }
+
+ @Test(expected = EJBTransactionRolledbackException.class)
+ public void testFindByPetNameRoleOwner() {
+ this.owner.run(this::testFindByPetNameNoRole);
+ }
+
+ @Test(expected = EJBTransactionRolledbackException.class)
+ public void testCreateRoleOwner() {
+ this.owner.run(this::testCreateNoRole);
+ }
+
+ @Test(expected = EJBTransactionRolledbackException.class)
+ public void testUpdateRoleOwner() {
+ this.owner.run(this::testUpdateNoRole);
+ }
+
+ @Test(expected = EJBTransactionRolledbackException.class)
+ public void testRemoveRoleOwner() {
+ this.owner.run(this::testRemoveNoRole);
+ }
+
+ @Test(expected = EJBTransactionRolledbackException.class)
+ public void testGetPetsRoleOwner() {
+ this.owner.run(this::testGetPetsNoRole);
+ }
+}
diff --git a/service/src/test/java/es/uvigo/esei/xcs/service/OwnerServiceIntegrationTest.java b/service/src/test/java/es/uvigo/esei/xcs/service/OwnerServiceIntegrationTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..064b8b1f49b21341786e85c40cd800182d696fe4
--- /dev/null
+++ b/service/src/test/java/es/uvigo/esei/xcs/service/OwnerServiceIntegrationTest.java
@@ -0,0 +1,255 @@
+package es.uvigo.esei.xcs.service;
+
+import static es.uvigo.esei.xcs.domain.entities.IsEqualsToOwner.containsOwnersInAnyOrder;
+import static es.uvigo.esei.xcs.domain.entities.IsEqualsToOwner.equalsToOwner;
+import static es.uvigo.esei.xcs.domain.entities.IsEqualsToPet.containsPetsInAnyOrder;
+import static es.uvigo.esei.xcs.domain.entities.OwnersDataset.anyOwner;
+import static es.uvigo.esei.xcs.domain.entities.OwnersDataset.newOwnerWithFreshPets;
+import static es.uvigo.esei.xcs.domain.entities.OwnersDataset.newOwnerWithPersistentPets;
+import static es.uvigo.esei.xcs.domain.entities.OwnersDataset.newOwnerWithoutPets;
+import static es.uvigo.esei.xcs.domain.entities.OwnersDataset.nonExistentLogin;
+import static es.uvigo.esei.xcs.domain.entities.OwnersDataset.nonExistentPetName;
+import static es.uvigo.esei.xcs.domain.entities.OwnersDataset.owner;
+import static es.uvigo.esei.xcs.domain.entities.OwnersDataset.ownerWithPets;
+import static es.uvigo.esei.xcs.domain.entities.OwnersDataset.ownerWithoutPets;
+import static es.uvigo.esei.xcs.domain.entities.OwnersDataset.owners;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.nullValue;
+import static org.hamcrest.collection.IsEmptyCollection.empty;
+import static org.junit.Assert.assertThat;
+
+import java.util.List;
+
+import javax.ejb.EJB;
+import javax.ejb.EJBTransactionRolledbackException;
+import javax.inject.Inject;
+
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.junit.Arquillian;
+import org.jboss.arquillian.persistence.CleanupUsingScript;
+import org.jboss.arquillian.persistence.ShouldMatchDataSet;
+import org.jboss.arquillian.persistence.UsingDataSet;
+import org.jboss.shrinkwrap.api.Archive;
+import org.jboss.shrinkwrap.api.ShrinkWrap;
+import org.jboss.shrinkwrap.api.asset.EmptyAsset;
+import org.jboss.shrinkwrap.api.spec.WebArchive;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import es.uvigo.esei.xcs.domain.entities.Owner;
+import es.uvigo.esei.xcs.domain.entities.OwnersDataset;
+import es.uvigo.esei.xcs.domain.entities.Pet;
+import es.uvigo.esei.xcs.service.util.security.RoleCaller;
+
+@RunWith(Arquillian.class)
+@UsingDataSet("owners.xml")
+@CleanupUsingScript({ "cleanup.sql", "cleanup-autoincrement.sql" })
+public class OwnerServiceIntegrationTest {
+ @Inject
+ private OwnerService facade;
+
+ @EJB(beanName = "admin-caller")
+ private RoleCaller admin;
+
+ @Deployment
+ public static Archive> createDeployment() {
+ final WebArchive archive = ShrinkWrap.create(WebArchive.class, "test.war")
+ .addClasses(OwnerService.class, OwnersDataset.class)
+ .addPackage(RoleCaller.class.getPackage())
+ .addPackage(Owner.class.getPackage())
+ .addAsResource("test-persistence.xml", "META-INF/persistence.xml")
+ .addAsWebInfResource("jboss-web.xml")
+ .addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml");
+
+ return archive;
+ }
+
+ @Test
+ @ShouldMatchDataSet("owners.xml")
+ public void testGetOwner() {
+ final String login = "pepe";
+ final Owner pepe = owner(login);
+
+ final Owner actual = admin.call(() -> facade.get(login));
+
+ assertThat(actual, is(equalsToOwner(pepe)));
+ }
+
+ @Test
+ @ShouldMatchDataSet("owners.xml")
+ public void testGetOwnerNonExistent() {
+ final String login = nonExistentLogin();
+
+ final Owner actual = admin.call(() -> facade.get(login));
+
+ assertThat(actual, is(nullValue()));
+ }
+
+ @Test(expected = EJBTransactionRolledbackException.class)
+ @ShouldMatchDataSet("owners.xml")
+ public void testGetOwnerNull() {
+ admin.call(() -> facade.get(null));
+ }
+
+ @Test
+ @ShouldMatchDataSet("owners.xml")
+ public void testList() {
+ final List actual = admin.call(() -> facade.list());
+
+ assertThat(actual, is(containsOwnersInAnyOrder(owners())));
+ }
+
+ @Test
+ @ShouldMatchDataSet("owners.xml")
+ public void testFindByPetName() {
+ final String pet = "Juandog";
+
+ final List owners = admin.call(() -> facade.findByPetName(pet));
+
+ final Owner owner = owners.get(0);
+ final Owner juan = owner("juan");
+ assertThat(owner, is(equalsToOwner(juan)));
+ }
+
+ @Test
+ @ShouldMatchDataSet("owners.xml")
+ public void testFindByPetNameMultipleOwners() {
+ final String pet = "Max";
+
+ final List owners = admin.call(() -> facade.findByPetName(pet));
+
+ final Owner[] expectedOwners = owners("juan", "ana");
+
+ assertThat(owners, containsOwnersInAnyOrder(expectedOwners));
+ }
+
+ @Test
+ @ShouldMatchDataSet("owners.xml")
+ public void testFindByPetNameNoPet() {
+ final String pet = nonExistentPetName();
+
+ final List owners = admin.call(() -> facade.findByPetName(pet));
+
+ assertThat(owners, is(empty()));
+ }
+
+ @Test(expected = EJBTransactionRolledbackException.class)
+ @ShouldMatchDataSet("owners.xml")
+ public void testFindByPetNameNull() {
+ admin.run(() -> facade.findByPetName(null));
+ }
+
+ @Test
+ @ShouldMatchDataSet({"owners.xml", "owners-create-without-pets.xml"})
+ public void testCreateWithoutPets() {
+ final Owner newOwner = newOwnerWithoutPets();
+
+ final Owner actual = admin.call(() -> facade.create(newOwner));
+
+ assertThat(actual, is(equalsToOwner(newOwner)));
+ }
+
+ @Test
+ @ShouldMatchDataSet({"owners.xml", "owners-create-with-pets.xml"})
+ public void testCreateWithPets() {
+ final Owner actual = admin.call(() -> facade.create(newOwnerWithFreshPets()));
+
+ assertThat(actual, is(equalsToOwner(newOwnerWithPersistentPets())));
+ }
+
+ @Test(expected = EJBTransactionRolledbackException.class)
+ @ShouldMatchDataSet("owners.xml")
+ public void testCreateExistentLogin() {
+ admin.run(() -> facade.create(anyOwner()));
+ }
+
+ @Test(expected = EJBTransactionRolledbackException.class)
+ @ShouldMatchDataSet("owners.xml")
+ public void testCreateNull() {
+ admin.call(() -> facade.create(null));
+ }
+
+ @Test
+ @ShouldMatchDataSet("owners-update-password.xml")
+ public void testUpdatePassword() {
+ final Owner owner = anyOwner();
+ owner.changePassword("newpassword");
+
+ admin.run(() -> facade.update(owner));
+ }
+
+ @Test
+ @ShouldMatchDataSet({"owners.xml", "owners-create-without-pets.xml"})
+ public void testUpdateNewOwnerWithoutPets() {
+ final Owner newOwner = newOwnerWithoutPets();
+
+ final Owner actual = admin.call(() -> facade.update(newOwner));
+
+ assertThat(actual, is(equalsToOwner(newOwner)));
+ }
+
+ @Test
+ @ShouldMatchDataSet({"owners.xml", "owners-create-with-pets.xml"})
+ public void testUpdateNewOwnerWithPets() {
+ final Owner actual = admin.call(() -> facade.update(newOwnerWithFreshPets()));
+
+ assertThat(actual, is(equalsToOwner(newOwnerWithPersistentPets())));
+ }
+
+ @Test
+ @ShouldMatchDataSet("owners-remove-without-pets.xml")
+ public void testRemoveWithoutPets() {
+ admin.run(() -> facade.remove(ownerWithoutPets().getLogin()));
+ }
+
+ @Test
+ @ShouldMatchDataSet("owners-remove-with-pets.xml")
+ public void testRemoveWithPets() {
+ admin.run(() -> facade.remove(ownerWithPets().getLogin()));
+ }
+
+ @Test(expected = EJBTransactionRolledbackException.class)
+ @ShouldMatchDataSet("owners.xml")
+ public void testRemoveNonExistentOwner() {
+ admin.run(() -> facade.remove(nonExistentLogin()));
+ }
+
+ @Test(expected = EJBTransactionRolledbackException.class)
+ @ShouldMatchDataSet("owners.xml")
+ public void testRemoveNull() {
+ admin.run(() -> facade.remove(null));
+ }
+
+ @Test
+ @ShouldMatchDataSet("owners.xml")
+ public void testGetPets() {
+ final Owner owner = ownerWithPets();
+ final Pet[] ownedPets = owner.getPets().toArray(new Pet[0]);
+
+ final List pets = admin.call(() -> facade.getPets(owner.getLogin()));
+
+ assertThat(pets, containsPetsInAnyOrder(ownedPets));
+ }
+
+ @Test
+ @ShouldMatchDataSet("owners.xml")
+ public void testGetPetsNoPets() {
+ final Owner owner = ownerWithoutPets();
+
+ final List pets = admin.call(() -> facade.getPets(owner.getLogin()));
+
+ assertThat(pets, is(empty()));
+ }
+
+ @Test(expected = EJBTransactionRolledbackException.class)
+ @ShouldMatchDataSet("owners.xml")
+ public void testGetPetsNonExistentOwner() {
+ admin.call(() -> facade.getPets(nonExistentLogin()));
+ }
+
+ @Test(expected = EJBTransactionRolledbackException.class)
+ @ShouldMatchDataSet("owners.xml")
+ public void testGetPetsNull() {
+ admin.call(() -> facade.getPets(null));
+ }
+}
diff --git a/service/src/test/java/es/uvigo/esei/xcs/service/PetServiceIllegalAccessIntegrationTest.java b/service/src/test/java/es/uvigo/esei/xcs/service/PetServiceIllegalAccessIntegrationTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..f619259eaf1fc20c60830a69a82922362355bc88
--- /dev/null
+++ b/service/src/test/java/es/uvigo/esei/xcs/service/PetServiceIllegalAccessIntegrationTest.java
@@ -0,0 +1,160 @@
+package es.uvigo.esei.xcs.service;
+
+import static es.uvigo.esei.xcs.domain.entities.OwnersDataset.anyPet;
+import static es.uvigo.esei.xcs.domain.entities.OwnersDataset.existentPetId;
+import static es.uvigo.esei.xcs.domain.entities.OwnersDataset.newPet;
+import static es.uvigo.esei.xcs.domain.entities.OwnersDataset.newPetWithOwner;
+import static es.uvigo.esei.xcs.domain.entities.OwnersDataset.owners;
+
+import javax.ejb.EJB;
+import javax.ejb.EJBAccessException;
+import javax.ejb.EJBTransactionRolledbackException;
+import javax.inject.Inject;
+
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.junit.Arquillian;
+import org.jboss.arquillian.persistence.CleanupUsingScript;
+import org.jboss.arquillian.persistence.ShouldMatchDataSet;
+import org.jboss.arquillian.persistence.TestExecutionPhase;
+import org.jboss.arquillian.persistence.UsingDataSet;
+import org.jboss.shrinkwrap.api.Archive;
+import org.jboss.shrinkwrap.api.ShrinkWrap;
+import org.jboss.shrinkwrap.api.spec.WebArchive;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import es.uvigo.esei.xcs.domain.entities.Owner;
+import es.uvigo.esei.xcs.domain.entities.OwnersDataset;
+import es.uvigo.esei.xcs.domain.entities.Pet;
+import es.uvigo.esei.xcs.service.util.security.RoleCaller;
+import es.uvigo.esei.xcs.service.util.security.TestPrincipal;
+
+@RunWith(Arquillian.class)
+@UsingDataSet("owners.xml")
+@ShouldMatchDataSet("owners.xml")
+@CleanupUsingScript(phase = TestExecutionPhase.BEFORE, value = { "cleanup.sql", "cleanup-autoincrement.sql" })
+public class PetServiceIllegalAccessIntegrationTest {
+ @Inject
+ private PetService facade;
+
+ @Inject
+ private TestPrincipal principal;
+
+ @EJB(beanName = "admin-caller")
+ private RoleCaller admin;
+
+ @EJB(beanName = "owner-caller")
+ private RoleCaller owner;
+
+ @Deployment
+ public static Archive> createDeployment() {
+ final WebArchive archive = ShrinkWrap.create(WebArchive.class, "test.war")
+ .addClasses(PetService.class, OwnersDataset.class)
+ .addPackage(RoleCaller.class.getPackage())
+ .addPackage(Pet.class.getPackage())
+ .addAsResource("test-persistence.xml", "META-INF/persistence.xml")
+ .addAsWebInfResource("jboss-web.xml")
+ .addAsWebInfResource("beans.xml", "beans.xml");
+
+ return archive;
+ }
+
+ @Test(expected = EJBAccessException.class)
+ public void testGetNoRole() {
+ facade.get(existentPetId());
+ }
+
+ @Test(expected = EJBAccessException.class)
+ public void testListNoRole() {
+ facade.list();
+ }
+
+ @Test(expected = EJBAccessException.class)
+ public void testCreateNoRole() {
+ facade.create(newPet());
+ }
+
+ @Test(expected = EJBAccessException.class)
+ public void testUpdateNoRole() {
+ facade.update(anyPet());
+ }
+
+ @Test(expected = EJBAccessException.class)
+ public void testRemoveNoRole() {
+ facade.remove(existentPetId());
+ }
+
+ @Test(expected = EJBTransactionRolledbackException.class)
+ public void testGetRoleAdmin() {
+ this.admin.run(this::testGetNoRole);
+ }
+
+ @Test(expected = EJBTransactionRolledbackException.class)
+ public void testListRoleAdmin() {
+ this.admin.run(this::testListNoRole);
+ }
+
+ @Test(expected = EJBTransactionRolledbackException.class)
+ public void testCreateRoleAdmin() {
+ this.admin.run(this::testCreateNoRole);
+ }
+
+ @Test(expected = EJBTransactionRolledbackException.class)
+ public void testUpdateRoleAdmin() {
+ this.admin.run(this::testUpdateNoRole);
+ }
+
+ @Test(expected = EJBTransactionRolledbackException.class)
+ public void testRemoveRoleAdmin() {
+ this.admin.run(this::testRemoveNoRole);
+ }
+
+ @Test(expected = EJBTransactionRolledbackException.class)
+ public void testGetRoleOwner() {
+ final Owner[] owners = owners();
+ final Owner owner1 = owners[0];
+ final Owner owner2 = owners[1];
+ final Pet pet1 = owner1.getPets().iterator().next();
+
+ principal.setName(owner2.getLogin());
+
+ this.owner.run(() -> this.facade.get(pet1.getId()));
+ }
+
+ @Test(expected = EJBTransactionRolledbackException.class)
+ public void testCreateRoleOwner() {
+ final Owner[] owners = owners();
+ final Owner owner1 = owners[0];
+ final Owner owner2 = owners[1];
+ final Pet pet = newPetWithOwner(owner1);
+
+ principal.setName(owner2.getLogin());
+
+ this.owner.run(() -> this.facade.create(pet));
+ }
+
+ @Test(expected = EJBTransactionRolledbackException.class)
+ public void testUpdateRoleOwner() {
+ final Owner[] owners = owners();
+ final Owner owner1 = owners[0];
+ final Owner owner2 = owners[1];
+ final Pet pet1 = owner1.getPets().iterator().next();
+ pet1.setName("Owner2 Pet");
+
+ principal.setName(owner2.getLogin());
+
+ this.owner.run(() -> this.facade.update(pet1));
+ }
+
+ @Test(expected = EJBTransactionRolledbackException.class)
+ public void testRemoveRoleOwner() {
+ final Owner[] owners = owners();
+ final Owner owner1 = owners[0];
+ final Owner owner2 = owners[1];
+ final Pet pet1 = owner1.getPets().iterator().next();
+
+ principal.setName(owner2.getLogin());
+
+ this.owner.run(() -> this.facade.remove(pet1.getId()));
+ }
+}
diff --git a/service/src/test/java/es/uvigo/esei/xcs/service/PetServiceIntegrationTest.java b/service/src/test/java/es/uvigo/esei/xcs/service/PetServiceIntegrationTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..0a944a3d94734d137f40bdbabbeec040f6b8c0fb
--- /dev/null
+++ b/service/src/test/java/es/uvigo/esei/xcs/service/PetServiceIntegrationTest.java
@@ -0,0 +1,250 @@
+package es.uvigo.esei.xcs.service;
+
+import static es.uvigo.esei.xcs.domain.entities.IsEqualsToPet.containsPetsInAnyOrder;
+import static es.uvigo.esei.xcs.domain.entities.IsEqualsToPet.equalsToPet;
+import static es.uvigo.esei.xcs.domain.entities.OwnersDataset.existentPetId;
+import static es.uvigo.esei.xcs.domain.entities.OwnersDataset.newPet;
+import static es.uvigo.esei.xcs.domain.entities.OwnersDataset.newPetWithOwner;
+import static es.uvigo.esei.xcs.domain.entities.OwnersDataset.nonExistentPetId;
+import static es.uvigo.esei.xcs.domain.entities.OwnersDataset.ownerWithPets;
+import static es.uvigo.esei.xcs.domain.entities.OwnersDataset.ownerWithoutPets;
+import static es.uvigo.esei.xcs.domain.entities.OwnersDataset.pet;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.nullValue;
+import static org.hamcrest.collection.IsEmptyCollection.empty;
+import static org.junit.Assert.assertThat;
+
+import java.util.Date;
+import java.util.List;
+
+import javax.ejb.EJB;
+import javax.ejb.EJBTransactionRolledbackException;
+import javax.inject.Inject;
+import javax.security.auth.login.LoginException;
+
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.junit.Arquillian;
+import org.jboss.arquillian.persistence.CleanupUsingScript;
+import org.jboss.arquillian.persistence.ShouldMatchDataSet;
+import org.jboss.arquillian.persistence.UsingDataSet;
+import org.jboss.shrinkwrap.api.Archive;
+import org.jboss.shrinkwrap.api.ShrinkWrap;
+import org.jboss.shrinkwrap.api.spec.WebArchive;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import es.uvigo.esei.xcs.domain.entities.AnimalType;
+import es.uvigo.esei.xcs.domain.entities.Owner;
+import es.uvigo.esei.xcs.domain.entities.OwnersDataset;
+import es.uvigo.esei.xcs.domain.entities.Pet;
+import es.uvigo.esei.xcs.service.util.security.RoleCaller;
+import es.uvigo.esei.xcs.service.util.security.TestPrincipal;
+
+@RunWith(Arquillian.class)
+@UsingDataSet("owners.xml")
+@CleanupUsingScript({ "cleanup.sql", "cleanup-autoincrement.sql" })
+public class PetServiceIntegrationTest {
+ @Inject
+ private PetService facade;
+
+ @EJB(beanName = "owner-caller")
+ private RoleCaller owner;
+
+ @Inject
+ private TestPrincipal principal;
+
+ @Deployment
+ public static Archive> createDeployment() {
+ final WebArchive archive = ShrinkWrap.create(WebArchive.class, "test.war")
+ .addClasses(PetService.class, OwnersDataset.class)
+ .addPackage(RoleCaller.class.getPackage())
+ .addPackage(Pet.class.getPackage())
+ .addAsResource("test-persistence.xml", "META-INF/persistence.xml")
+ .addAsWebInfResource("jboss-web.xml")
+ .addAsWebInfResource("beans.xml", "beans.xml");
+
+ return archive;
+ }
+
+ @Test
+ @ShouldMatchDataSet("owners.xml")
+ public void testGet() throws LoginException {
+ final int id = existentPetId();
+ final Pet pet = pet(id);
+ this.principal.setName(pet.getOwner().getLogin());
+
+ final Pet actual = this.owner.call(() -> facade.get(id));
+
+ assertThat(actual, equalsToPet(pet));
+ }
+
+ @Test
+ @ShouldMatchDataSet("owners.xml")
+ public void testGetBadId() throws LoginException {
+ final int id = nonExistentPetId();
+
+ this.principal.setName(ownerWithoutPets().getLogin());
+
+ final Pet actual = this.owner.call(() -> facade.get(id));
+
+ assertThat(actual, is(nullValue()));
+ }
+
+ @Test(expected = EJBTransactionRolledbackException.class)
+ @ShouldMatchDataSet("owners.xml")
+ public void testGetOthersPetId() throws LoginException {
+ final Owner ownerWithoutPets = ownerWithoutPets();
+ final Owner ownerWithPets = ownerWithPets();
+ final int petId = ownerWithPets.getPets().iterator().next().getId();
+
+ this.principal.setName(ownerWithoutPets.getLogin());
+
+ this.owner.run(() -> facade.get(petId));
+ }
+
+ @Test
+ @ShouldMatchDataSet("owners.xml")
+ public void testList() throws LoginException {
+ final Owner owner = ownerWithPets();
+ final Pet[] ownedPets = owner.getPets().toArray(new Pet[0]);
+ this.principal.setName(owner.getLogin());
+
+ final List pets = this.owner.call(() -> facade.list());
+
+ assertThat(pets, containsPetsInAnyOrder(ownedPets));
+ }
+
+ @Test
+ @ShouldMatchDataSet("owners.xml")
+ public void testListNoPets() throws LoginException {
+ final Owner owner = ownerWithoutPets();
+
+ this.principal.setName(owner.getLogin());
+
+ final List pets = this.owner.call(() -> facade.list());
+
+ assertThat(pets, is(empty()));
+ }
+
+ @Test
+ @ShouldMatchDataSet({ "owners.xml", "owners-create-pet.xml" })
+ public void testCreate() {
+ final Owner owner = ownerWithoutPets();
+ this.principal.setName(owner.getLogin());
+
+ final Pet pet = newPet();
+
+ this.owner.call(() -> facade.create(pet));
+ }
+
+ @Test(expected = EJBTransactionRolledbackException.class)
+ @ShouldMatchDataSet({ "owners.xml" })
+ public void testCreateNull() {
+ this.principal.setName(ownerWithoutPets().getLogin());
+
+ this.owner.run(() -> facade.create(null));
+ }
+
+ @Test(expected = EJBTransactionRolledbackException.class)
+ @ShouldMatchDataSet({ "owners.xml" })
+ public void testCreateWrongOwner() {
+ final Owner owner = ownerWithoutPets();
+ final Owner otherOwner = ownerWithPets();
+
+ this.principal.setName(owner.getLogin());
+
+ final Pet pet = newPetWithOwner(otherOwner);
+
+ this.owner.run(() -> facade.create(pet));
+ }
+
+ @Test
+ @ShouldMatchDataSet("owners-update-pet.xml")
+ public void testUpdate() throws LoginException {
+ final int id = existentPetId();
+ final Pet pet = pet(id);
+
+ this.principal.setName(pet.getOwner().getLogin());
+
+ pet.setName("UpdateName");
+ pet.setAnimal(AnimalType.BIRD);
+ pet.setBirth(new Date(946771261000L));
+
+ this.owner.run(() -> facade.update(pet));
+ }
+
+ @Test
+ @ShouldMatchDataSet({ "owners.xml", "owners-create-pet.xml" })
+ public void testUpdateNewPetWithOwner() {
+ final Owner owner = ownerWithoutPets();
+ this.principal.setName(owner.getLogin());
+
+ final Pet pet = newPetWithOwner(owner);
+
+ this.owner.call(() -> facade.update(pet));
+ }
+
+ @Test(expected = EJBTransactionRolledbackException.class)
+ @ShouldMatchDataSet("owners.xml")
+ public void testUpdateNull() throws LoginException {
+ this.owner.run(() -> facade.update(null));
+ }
+
+ @Test(expected = EJBTransactionRolledbackException.class)
+ @ShouldMatchDataSet({ "owners.xml" })
+ public void testUpdateWrongOwner() {
+ final Owner owner = ownerWithoutPets();
+ final Owner otherOwner = ownerWithPets();
+
+ this.principal.setName(owner.getLogin());
+
+ final Pet pet = otherOwner.getPets().iterator().next();
+
+ this.owner.run(() -> facade.update(pet));
+ }
+
+ @Test(expected = EJBTransactionRolledbackException.class)
+ @ShouldMatchDataSet({ "owners.xml", "owners-create-pet.xml" })
+ public void testUpdatePetNoOwner() {
+ final int id = existentPetId();
+ final Pet pet = pet(id);
+
+ this.principal.setName(pet.getOwner().getLogin());
+ pet.setOwner(null);
+
+
+ this.owner.run(() -> facade.update(pet));
+ }
+
+ @Test
+ @ShouldMatchDataSet("owners-remove-pet.xml")
+ public void testRemove() throws LoginException {
+ final int id = existentPetId();
+ final Pet pet = pet(id);
+ this.principal.setName(pet.getOwner().getLogin());
+
+ this.owner.run(() -> facade.remove(id));
+ }
+
+ @Test(expected = EJBTransactionRolledbackException.class)
+ @ShouldMatchDataSet("owners.xml")
+ public void testRemoveBadId() throws LoginException {
+ final int id = nonExistentPetId();
+
+ this.principal.setName(ownerWithoutPets().getLogin());
+
+ this.owner.run(() -> facade.remove(id));
+ }
+
+ @Test(expected = EJBTransactionRolledbackException.class)
+ @ShouldMatchDataSet("owners.xml")
+ public void testRemoveOthersPetId() throws LoginException {
+ final Owner ownerWithoutPets = ownerWithoutPets();
+ final Owner ownerWithPets = ownerWithPets();
+ final int petId = ownerWithPets.getPets().iterator().next().getId();
+
+ this.principal.setName(ownerWithoutPets.getLogin());
+
+ this.owner.run(() -> facade.remove(petId));
+ }
+}
diff --git a/service/src/test/java/es/uvigo/esei/xcs/service/ServiceIntegrationTestSuite.java b/service/src/test/java/es/uvigo/esei/xcs/service/ServiceIntegrationTestSuite.java
new file mode 100644
index 0000000000000000000000000000000000000000..fe0cb61d0beec0a08234e2c4e136d34456b505ce
--- /dev/null
+++ b/service/src/test/java/es/uvigo/esei/xcs/service/ServiceIntegrationTestSuite.java
@@ -0,0 +1,15 @@
+package es.uvigo.esei.xcs.service;
+
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+import org.junit.runners.Suite.SuiteClasses;
+
+@RunWith(Suite.class)
+@SuiteClasses({
+ OwnerServiceIntegrationTest.class,
+ OwnerServiceIllegalAccessIntegrationTest.class,
+ PetServiceIntegrationTest.class,
+ PetServiceIllegalAccessIntegrationTest.class
+})
+public class ServiceIntegrationTestSuite {
+}
diff --git a/service/src/test/java/es/uvigo/esei/xcs/service/util/security/AdminRoleCaller.java b/service/src/test/java/es/uvigo/esei/xcs/service/util/security/AdminRoleCaller.java
new file mode 100644
index 0000000000000000000000000000000000000000..1c65ed4bb5962925740b3db864c51143aa48c36e
--- /dev/null
+++ b/service/src/test/java/es/uvigo/esei/xcs/service/util/security/AdminRoleCaller.java
@@ -0,0 +1,29 @@
+package es.uvigo.esei.xcs.service.util.security;
+
+import java.util.function.Supplier;
+
+import javax.annotation.security.PermitAll;
+import javax.annotation.security.RunAs;
+import javax.ejb.Stateless;
+
+@Stateless(name = "admin-caller")
+@RunAs("ADMIN")
+@PermitAll
+public class AdminRoleCaller implements RoleCaller {
+ public V call(Supplier supplier) {
+ return supplier.get();
+ }
+
+ public void run(Runnable run) {
+ run.run();
+ }
+
+ public V throwingCall(ThrowingSupplier supplier) throws Throwable {
+ return supplier.get();
+ }
+
+ public void throwingRun(ThrowingRunnable run) throws Throwable{
+ run.run();
+ }
+}
+
diff --git a/service/src/test/java/es/uvigo/esei/xcs/service/util/security/OwnerRoleCaller.java b/service/src/test/java/es/uvigo/esei/xcs/service/util/security/OwnerRoleCaller.java
new file mode 100644
index 0000000000000000000000000000000000000000..0cc36efc4af5439c6c7a02312d6a5f971c038114
--- /dev/null
+++ b/service/src/test/java/es/uvigo/esei/xcs/service/util/security/OwnerRoleCaller.java
@@ -0,0 +1,28 @@
+package es.uvigo.esei.xcs.service.util.security;
+
+import java.util.function.Supplier;
+
+import javax.annotation.security.PermitAll;
+import javax.annotation.security.RunAs;
+import javax.ejb.Stateless;
+
+@Stateless(name = "owner-caller")
+@RunAs("OWNER")
+@PermitAll
+public class OwnerRoleCaller implements RoleCaller {
+ public V call(Supplier supplier) {
+ return supplier.get();
+ }
+
+ public void run(Runnable run) {
+ run.run();
+ }
+
+ public V throwingCall(ThrowingSupplier supplier) throws Throwable {
+ return supplier.get();
+ }
+
+ public void throwingRun(ThrowingRunnable run) throws Throwable{
+ run.run();
+ }
+}
diff --git a/service/src/test/java/es/uvigo/esei/xcs/service/util/security/RoleCaller.java b/service/src/test/java/es/uvigo/esei/xcs/service/util/security/RoleCaller.java
new file mode 100644
index 0000000000000000000000000000000000000000..92cd46fe7747db9f0dccdf1e2e5386c814388e32
--- /dev/null
+++ b/service/src/test/java/es/uvigo/esei/xcs/service/util/security/RoleCaller.java
@@ -0,0 +1,21 @@
+package es.uvigo.esei.xcs.service.util.security;
+
+import java.util.function.Supplier;
+
+public interface RoleCaller {
+ public V call(Supplier supplier);
+
+ public void run(Runnable run);
+
+ public V throwingCall(ThrowingSupplier supplier) throws Throwable;
+
+ public void throwingRun(ThrowingRunnable run) throws Throwable;
+
+ public interface ThrowingRunnable {
+ public void run() throws Throwable;
+ }
+
+ public interface ThrowingSupplier {
+ public V get() throws Throwable;
+ }
+}
diff --git a/service/src/test/java/es/uvigo/esei/xcs/service/util/security/TestPrincipal.java b/service/src/test/java/es/uvigo/esei/xcs/service/util/security/TestPrincipal.java
new file mode 100644
index 0000000000000000000000000000000000000000..bd34e6a040971ad26ddb65e8f200b523f3891b15
--- /dev/null
+++ b/service/src/test/java/es/uvigo/esei/xcs/service/util/security/TestPrincipal.java
@@ -0,0 +1,27 @@
+package es.uvigo.esei.xcs.service.util.security;
+
+import java.security.Principal;
+
+import javax.enterprise.inject.Alternative;
+import javax.inject.Singleton;
+
+@Alternative
+@Singleton
+public class TestPrincipal implements Principal {
+ private String name;
+
+ public TestPrincipal() {}
+
+ public TestPrincipal(String name) {
+ this.name = name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+}
\ No newline at end of file
diff --git a/service/src/test/resources-wildfly-embedded-h2/beans.xml b/service/src/test/resources-wildfly-embedded-h2/beans.xml
new file mode 100644
index 0000000000000000000000000000000000000000..01d52d1a567d583d8353fdb98e65e827ff09ebac
--- /dev/null
+++ b/service/src/test/resources-wildfly-embedded-h2/beans.xml
@@ -0,0 +1,11 @@
+
+
+
+ es.uvigo.esei.xcs.service.util.security.TestPrincipal
+
+
+
diff --git a/service/src/test/resources-wildfly-embedded-h2/cleanup-autoincrement.sql b/service/src/test/resources-wildfly-embedded-h2/cleanup-autoincrement.sql
new file mode 100644
index 0000000000000000000000000000000000000000..245049ca05efb8bd0cb20c838880162d9623d3e7
--- /dev/null
+++ b/service/src/test/resources-wildfly-embedded-h2/cleanup-autoincrement.sql
@@ -0,0 +1 @@
+ALTER TABLE Pet ALTER COLUMN id RESTART WITH 1;
\ No newline at end of file
diff --git a/service/src/test/resources-wildfly-embedded-h2/jboss-web.xml b/service/src/test/resources-wildfly-embedded-h2/jboss-web.xml
new file mode 100644
index 0000000000000000000000000000000000000000..68c92827d5a6f787d0e89d9f7f445097bd1ad261
--- /dev/null
+++ b/service/src/test/resources-wildfly-embedded-h2/jboss-web.xml
@@ -0,0 +1,4 @@
+
+
+ xcs-sample-security-domain
+
\ No newline at end of file
diff --git a/service/src/test/resources-wildfly-embedded-h2/standalone.xml b/service/src/test/resources-wildfly-embedded-h2/standalone.xml
new file mode 100644
index 0000000000000000000000000000000000000000..fd979b90f80cf7c8973b9e3615c217f8177f7f25
--- /dev/null
+++ b/service/src/test/resources-wildfly-embedded-h2/standalone.xml
@@ -0,0 +1,415 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
+ h2
+
+ sa
+ sa
+
+
+
+
+ org.h2.jdbcx.JdbcDataSource
+
+
+
+
+
+
+
+
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ${jboss.bind.address:127.0.0.1}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/service/src/test/resources-wildfly-embedded-h2/test-persistence.xml b/service/src/test/resources-wildfly-embedded-h2/test-persistence.xml
new file mode 100644
index 0000000000000000000000000000000000000000..ae6b5d32518772eaccca0143292dd26d1324aabf
--- /dev/null
+++ b/service/src/test/resources-wildfly-embedded-h2/test-persistence.xml
@@ -0,0 +1,17 @@
+
+
+
+ java:jboss/datasources/ExampleDS
+
+ false
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/service/src/test/resources-wildfly-embedded-mysql/beans.xml b/service/src/test/resources-wildfly-embedded-mysql/beans.xml
new file mode 100644
index 0000000000000000000000000000000000000000..01d52d1a567d583d8353fdb98e65e827ff09ebac
--- /dev/null
+++ b/service/src/test/resources-wildfly-embedded-mysql/beans.xml
@@ -0,0 +1,11 @@
+
+
+
+ es.uvigo.esei.xcs.service.util.security.TestPrincipal
+
+
+
diff --git a/service/src/test/resources-wildfly-embedded-mysql/cleanup-autoincrement.sql b/service/src/test/resources-wildfly-embedded-mysql/cleanup-autoincrement.sql
new file mode 100644
index 0000000000000000000000000000000000000000..a51d23be2cbb2664431732170bda027e04dda9d5
--- /dev/null
+++ b/service/src/test/resources-wildfly-embedded-mysql/cleanup-autoincrement.sql
@@ -0,0 +1 @@
+ALTER TABLE Pet AUTO_INCREMENT = 1;
\ No newline at end of file
diff --git a/service/src/test/resources-wildfly-embedded-mysql/jboss-web.xml b/service/src/test/resources-wildfly-embedded-mysql/jboss-web.xml
new file mode 100644
index 0000000000000000000000000000000000000000..68c92827d5a6f787d0e89d9f7f445097bd1ad261
--- /dev/null
+++ b/service/src/test/resources-wildfly-embedded-mysql/jboss-web.xml
@@ -0,0 +1,4 @@
+
+
+ xcs-sample-security-domain
+
\ No newline at end of file
diff --git a/service/src/test/resources-wildfly-embedded-mysql/mysql-ds.xml b/service/src/test/resources-wildfly-embedded-mysql/mysql-ds.xml
new file mode 100644
index 0000000000000000000000000000000000000000..e35c79b61bcb83eaddf8d22303e1eff0e3bbf450
--- /dev/null
+++ b/service/src/test/resources-wildfly-embedded-mysql/mysql-ds.xml
@@ -0,0 +1,17 @@
+
+
+
+ jdbc:mysql://localhost:3306/xcs
+ mysql-connector-java-${mysql.version}.jar
+
+ 30
+
+
+ xcs
+ xcs
+
+
+
+
\ No newline at end of file
diff --git a/service/src/test/resources-wildfly-embedded-mysql/standalone.xml b/service/src/test/resources-wildfly-embedded-mysql/standalone.xml
new file mode 100644
index 0000000000000000000000000000000000000000..28088fde0c74abbb7ec04a1862e685f4ddf4e029
--- /dev/null
+++ b/service/src/test/resources-wildfly-embedded-mysql/standalone.xml
@@ -0,0 +1,415 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
+ h2
+
+ sa
+ sa
+
+
+
+
+ org.h2.jdbcx.JdbcDataSource
+
+
+
+
+
+
+
+
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ${jboss.bind.address:127.0.0.1}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/service/src/test/resources-wildfly-embedded-mysql/test-persistence.xml b/service/src/test/resources-wildfly-embedded-mysql/test-persistence.xml
new file mode 100644
index 0000000000000000000000000000000000000000..1d6b2be6a710d0acf94eacf057af32d6b8849452
--- /dev/null
+++ b/service/src/test/resources-wildfly-embedded-mysql/test-persistence.xml
@@ -0,0 +1,17 @@
+
+
+
+ java:jboss/datasources/xcs
+
+ false
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/service/src/test/resources/arquillian.xml b/service/src/test/resources/arquillian.xml
new file mode 100644
index 0000000000000000000000000000000000000000..281724dfe0949922afa48ce5ee3fd171f7ce378e
--- /dev/null
+++ b/service/src/test/resources/arquillian.xml
@@ -0,0 +1,25 @@
+
+
+
+
+ CLEAN_INSERT
+
+
+
+
+ target/wildfly-${wildfly.version}
+ target/wildfly-${wildfly.version}/modules
+
+
+
+
+
+ target/wildfly-${wildfly.version}
+ target/wildfly-${wildfly.version}/modules
+
+
+
\ No newline at end of file
diff --git a/service/src/test/resources/datasets/owners-create-pet.xml b/service/src/test/resources/datasets/owners-create-pet.xml
new file mode 100644
index 0000000000000000000000000000000000000000..44f301e552de28b46c4d819d30fa568f803eb5bb
--- /dev/null
+++ b/service/src/test/resources/datasets/owners-create-pet.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/service/src/test/resources/datasets/owners-create-with-pets.xml b/service/src/test/resources/datasets/owners-create-with-pets.xml
new file mode 100644
index 0000000000000000000000000000000000000000..f581406c2248d67ea5a968a1b23d910c44f6ccaf
--- /dev/null
+++ b/service/src/test/resources/datasets/owners-create-with-pets.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/service/src/test/resources/datasets/owners-create-without-pets.xml b/service/src/test/resources/datasets/owners-create-without-pets.xml
new file mode 100644
index 0000000000000000000000000000000000000000..ce918d41c2e14db21fd035ee416362def53bc3fd
--- /dev/null
+++ b/service/src/test/resources/datasets/owners-create-without-pets.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/service/src/test/resources/datasets/owners-remove-pet.xml b/service/src/test/resources/datasets/owners-remove-pet.xml
new file mode 100644
index 0000000000000000000000000000000000000000..959cb6e355930825f2110f963b6e4ad744e3b107
--- /dev/null
+++ b/service/src/test/resources/datasets/owners-remove-pet.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/service/src/test/resources/datasets/owners-remove-with-pets.xml b/service/src/test/resources/datasets/owners-remove-with-pets.xml
new file mode 100644
index 0000000000000000000000000000000000000000..6b5fa24feb95fa28d239b6401e36a995cd26d09e
--- /dev/null
+++ b/service/src/test/resources/datasets/owners-remove-with-pets.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/service/src/test/resources/datasets/owners-remove-without-pets.xml b/service/src/test/resources/datasets/owners-remove-without-pets.xml
new file mode 100644
index 0000000000000000000000000000000000000000..4498c9eeb653223f4783ba2f1f70be2137a7a97d
--- /dev/null
+++ b/service/src/test/resources/datasets/owners-remove-without-pets.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/service/src/test/resources/datasets/owners-update-password.xml b/service/src/test/resources/datasets/owners-update-password.xml
new file mode 100644
index 0000000000000000000000000000000000000000..4c0f8e17034316cfbaf4db6f71fee6840269a659
--- /dev/null
+++ b/service/src/test/resources/datasets/owners-update-password.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/service/src/test/resources/datasets/owners-update-pet.xml b/service/src/test/resources/datasets/owners-update-pet.xml
new file mode 100644
index 0000000000000000000000000000000000000000..b703c8b4d7668c2a2de462db9cd8f3396a5fba77
--- /dev/null
+++ b/service/src/test/resources/datasets/owners-update-pet.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/service/src/test/resources/datasets/owners.xml b/service/src/test/resources/datasets/owners.xml
new file mode 100644
index 0000000000000000000000000000000000000000..9d770d3d5a6b6fbbc4e2b9b32cf39070e51d2ba6
--- /dev/null
+++ b/service/src/test/resources/datasets/owners.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/service/src/test/resources/scripts/cleanup.sql b/service/src/test/resources/scripts/cleanup.sql
new file mode 100644
index 0000000000000000000000000000000000000000..d11e639af04b72cd085616b63b32b042d924bbdd
--- /dev/null
+++ b/service/src/test/resources/scripts/cleanup.sql
@@ -0,0 +1,2 @@
+DELETE FROM Pet;
+DELETE FROM User;
\ No newline at end of file