> getClasses() {
- return new HashSet<>(Arrays.asList(
- PeopleResource.class
- ));
+ return Stream.of(PeopleResource.class)
+ .collect(Collectors.toSet());
}
@Override
diff --git a/src/main/java/es/uvigo/esei/daa/LoginFilter.java b/src/main/java/es/uvigo/esei/daa/LoginFilter.java
index 8e3cd50fa85cdf89a3cb6b321c5c94d4c00b2ecc..4860187882c93b75cc07fb1b7c935dd5573b2ef4 100644
--- a/src/main/java/es/uvigo/esei/daa/LoginFilter.java
+++ b/src/main/java/es/uvigo/esei/daa/LoginFilter.java
@@ -1,6 +1,9 @@
package es.uvigo.esei.daa;
+import static java.util.Objects.requireNonNull;
+
import java.io.IOException;
+import java.util.Base64;
import java.util.Optional;
import javax.servlet.Filter;
@@ -17,8 +20,22 @@ import javax.servlet.http.HttpServletResponse;
import es.uvigo.esei.daa.dao.DAOException;
import es.uvigo.esei.daa.dao.UsersDAO;
+/**
+ * Security filter that implements a login protocol based on the HTTP Basic
+ * Authentication protocol. In this case, the login and password can be provided
+ * as plain request parameters or as a cookie named "token" that should contain
+ * both values in the same format as HTTP Basic Authentication
+ * ({@code base64(login + ":" + password)}).
+ *
+ * @author Miguel Reboiro Jato
+ *
+ */
@WebFilter(urlPatterns = { "/*", "/logout" })
public class LoginFilter implements Filter {
+ private static final String REST_PATH = "/rest";
+ private static final String INDEX_PATH = "/index.html";
+ private static final String LOGOUT_PATH = "/logout";
+
@Override
public void doFilter(
ServletRequest request,
@@ -47,17 +64,25 @@ public class LoginFilter implements Filter {
httpResponse.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
}
}
+
+ @Override
+ public void init(FilterConfig config) throws ServletException {
+ }
+
+ @Override
+ public void destroy() {
+ }
private boolean isLogoutPath(HttpServletRequest request) {
- return request.getServletPath().equals("/logout");
+ return request.getServletPath().equals(LOGOUT_PATH);
}
private boolean isIndexPath(HttpServletRequest request) {
- return request.getServletPath().equals("/index.html");
+ return request.getServletPath().equals(INDEX_PATH);
}
private boolean isRestPath(HttpServletRequest request) {
- return request.getServletPath().startsWith("/rest");
+ return request.getServletPath().startsWith(REST_PATH);
}
private void redirectToIndex(
@@ -92,14 +117,15 @@ public class LoginFilter implements Filter {
final String password = request.getParameter("password");
if (login != null && password != null) {
- final String token = new UsersDAO().checkLogin(login, password);
-
- if (token == null) {
- return false;
- } else {
- response.addCookie(new Cookie("token", token));
+ final UsersDAO dao = new UsersDAO();
+ if (dao.checkLogin(login, password)) {
+ final Credentials credentials = new Credentials(login, password);
+
+ response.addCookie(new Cookie("token", credentials.toToken()));
return true;
+ } else {
+ return false;
}
} else {
return false;
@@ -113,20 +139,56 @@ public class LoginFilter implements Filter {
for (Cookie cookie : cookies) {
if ("token".equals(cookie.getName())) {
- final String token = new UsersDAO().checkToken(cookie.getValue());
+ final Credentials credentials = new Credentials(cookie.getValue());
- return token != null;
+ final UsersDAO dao = new UsersDAO();
+
+ return dao.checkLogin(credentials.getLogin(), credentials.getPassword());
}
}
return false;
}
-
- @Override
- public void init(FilterConfig config) throws ServletException {
- }
-
- @Override
- public void destroy() {
+
+ private static class Credentials {
+ private final String login;
+ private final String password;
+
+ public Credentials(String token) {
+ final String decodedToken = decodeBase64(token);
+ final int colonIndex = decodedToken.indexOf(':');
+
+ if (colonIndex < 0 || colonIndex == decodedToken.length()-1) {
+ throw new IllegalArgumentException("Invalid token");
+ }
+
+ this.login = decodedToken.substring(0, colonIndex);
+ this.password = decodedToken.substring(colonIndex + 1);
+ }
+
+ public Credentials(String login, String password) {
+ this.login = requireNonNull(login, "Login can't be null");
+ this.password = requireNonNull(password, "Password can't be null");
+ }
+
+ public String getLogin() {
+ return login;
+ }
+
+ public String getPassword() {
+ return password;
+ }
+
+ public String toToken() {
+ return encodeBase64(this.login + ":" + this.password);
+ }
+
+ private final static String decodeBase64(String text) {
+ return new String(Base64.getDecoder().decode(text.getBytes()));
+ }
+
+ private final static String encodeBase64(String text) {
+ return Base64.getEncoder().encodeToString(text.getBytes());
+ }
}
}
diff --git a/src/main/java/es/uvigo/esei/daa/dao/DAO.java b/src/main/java/es/uvigo/esei/daa/dao/DAO.java
index 0c2320d17fc7c40039d51600b97407069d1601c6..1a83eee76744fcedcb13c5179da85cd2d1124a42 100644
--- a/src/main/java/es/uvigo/esei/daa/dao/DAO.java
+++ b/src/main/java/es/uvigo/esei/daa/dao/DAO.java
@@ -10,25 +10,41 @@ import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;
+/**
+ * Simple base class for DAO (Data Access Object) classes. This super-class is
+ * responsible for providing a {@link java.sql.Connection} to its sub-classes.
+ *
+ * @author Miguel Reboiro Jato
+ *
+ */
public abstract class DAO {
- private final static Logger LOG = Logger.getLogger("DAO");
+ private final static Logger LOG = Logger.getLogger(DAO.class.getName());
private final static String JNDI_NAME = "java:/comp/env/jdbc/daaexample";
private DataSource dataSource;
+ /**
+ * Constructs a new instance of {@link DAO}.
+ */
public DAO() {
Context initContext;
try {
initContext = new InitialContext();
- this.dataSource = (DataSource) initContext.lookup(
- System.getProperty("db.jndi", JNDI_NAME)
- );
+
+ this.dataSource = (DataSource) initContext.lookup(JNDI_NAME);
} catch (NamingException e) {
LOG.log(Level.SEVERE, "Error initializing DAO", e);
throw new RuntimeException(e);
}
}
+ /**
+ * Returns an open {@link java.sql.Connection}.
+ *
+ * @return an open {@link java.sql.Connection}.
+ * @throws SQLException if an error happens while establishing the
+ * connection with the database.
+ */
protected Connection getConnection() throws SQLException {
return this.dataSource.getConnection();
}
diff --git a/src/main/java/es/uvigo/esei/daa/dao/DAOException.java b/src/main/java/es/uvigo/esei/daa/dao/DAOException.java
index fda528bfa123ec4ad6c272dc0e7235b205a64438..ffd4233f07cfcbbed73c264c235efd0317b9ffcf 100644
--- a/src/main/java/es/uvigo/esei/daa/dao/DAOException.java
+++ b/src/main/java/es/uvigo/esei/daa/dao/DAOException.java
@@ -1,23 +1,81 @@
package es.uvigo.esei.daa.dao;
+/**
+ * A general exception class for the DAO layer.
+ *
+ * @author Miguel Reboiro Jato
+ */
public class DAOException extends Exception {
private static final long serialVersionUID = 1L;
+ /**
+ * Constructs a new instance of {@link DAOException} with {@code null} as
+ * its detail message.
+ * The cause is not initialized, and may subsequently be initialized by a
+ * call to {@link #initCause}.
+ *
+ */
public DAOException() {
}
+ /**
+ * Constructs a new instance of {@link DAOException} with the specified
+ * detail message. The cause is not initialized, and may subsequently be
+ * initialized by a call to {@link #initCause}.
+ *
+ * @param message the detail message. The detail message is saved for later
+ * retrieval by the {@link #getMessage()} method.
+ */
public DAOException(String message) {
super(message);
}
+ /**
+ * Constructs a new instance of {@link DAOException} with the specified
+ * cause and a detail message of
+ * {@code (cause==null ? null : cause.toString())} (which typically contains
+ * the class and detail message of {@code cause}). This constructor is
+ * useful for exceptions that are little more than wrappers for other
+ * throwables (for example, {@link java.security.PrivilegedActionException}).
+ *
+ * @param cause the cause (which is saved for later retrieval by the
+ * {@link #getCause()} method). (A {@code null} value is permitted, and
+ * indicates that the cause is nonexistent or unknown.)
+ */
public DAOException(Throwable cause) {
super(cause);
}
+ /**
+ * Constructs a new instance of {@link DAOException} with the specified
+ * detail message and cause.
+ *
+ * Note that the detail message associated with {@code cause} is
+ * not automatically incorporated in this exception's detail message.
+ *
+ * @param message the detail message (which is saved for later retrieval
+ * by the {@link #getMessage()} method).
+ * @param cause the cause (which is saved for later retrieval by the
+ * {@link #getCause()} method). A {@code null} value is permitted, and
+ * indicates that the cause is nonexistent or unknown.
+ */
public DAOException(String message, Throwable cause) {
super(message, cause);
}
+ /**
+ * Constructs a new instance of {@link DAOException} with the specified
+ * detail message, cause, suppression enabled or disabled, and writable
+ * stack trace enabled or disabled.
+ *
+ * @param message the detail message.
+ * @param cause the cause. A {@code null} value is permitted, and indicates
+ * that the cause is nonexistent or unknown.
+ * @param enableSuppression whether or not suppression is enabled or
+ * disabled.
+ * @param writableStackTrace whether or not the stack trace should be
+ * writable.
+ */
public DAOException(String message, Throwable cause,
boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
diff --git a/src/main/java/es/uvigo/esei/daa/dao/PeopleDAO.java b/src/main/java/es/uvigo/esei/daa/dao/PeopleDAO.java
index dfbbb13ca1c6bb28416d0d8eda6ffc0f87c85084..1d99edb26140ee773f06c8afbf0f40923f1848b2 100644
--- a/src/main/java/es/uvigo/esei/daa/dao/PeopleDAO.java
+++ b/src/main/java/es/uvigo/esei/daa/dao/PeopleDAO.java
@@ -12,9 +12,24 @@ import java.util.logging.Logger;
import es.uvigo.esei.daa.entities.Person;
+/**
+ * DAO class for the {@link Person} entities.
+ *
+ * @author Miguel Reboiro Jato
+ *
+ */
public class PeopleDAO extends DAO {
- private final static Logger LOG = Logger.getLogger("PeopleDAO");
+ private final static Logger LOG = Logger.getLogger(PeopleDAO.class.getName());
+ /**
+ * Returns a person stored persisted in the system.
+ *
+ * @param id identifier of the person.
+ * @return a person with the provided identifier.
+ * @throws DAOException if an error happens while retrieving the person.
+ * @throws IllegalArgumentException if the provided id does not corresponds
+ * with any persisted person.
+ */
public Person get(int id)
throws DAOException, IllegalArgumentException {
try (final Connection conn = this.getConnection()) {
@@ -25,11 +40,7 @@ public class PeopleDAO extends DAO {
try (final ResultSet result = statement.executeQuery()) {
if (result.next()) {
- return new Person(
- result.getInt("id"),
- result.getString("name"),
- result.getString("surname")
- );
+ return rowToEntity(result);
} else {
throw new IllegalArgumentException("Invalid id");
}
@@ -41,6 +52,12 @@ public class PeopleDAO extends DAO {
}
}
+ /**
+ * Returns a list with all the people persisted in the system.
+ *
+ * @return a list with all the people persisted in the system.
+ * @throws DAOException if an error happens while retrieving the people.
+ */
public List list() throws DAOException {
try (final Connection conn = this.getConnection()) {
final String query = "SELECT * FROM people";
@@ -50,11 +67,7 @@ public class PeopleDAO extends DAO {
final List people = new LinkedList<>();
while (result.next()) {
- people.add(new Person(
- result.getInt("id"),
- result.getString("name"),
- result.getString("surname")
- ));
+ people.add(rowToEntity(result));
}
return people;
@@ -66,41 +79,73 @@ public class PeopleDAO extends DAO {
}
}
- public void delete(int id)
+ /**
+ * Persists a new person in the system. An identifier will be assigned
+ * automatically to the new person.
+ *
+ * @param name name of the new person. Can't be {@code null}.
+ * @param surname surname of the new person. Can't be {@code null}.
+ * @return a {@link Person} entity representing the persisted person.
+ * @throws DAOException if an error happens while persisting the new person.
+ * @throws IllegalArgumentException if the name or surname are {@code null}.
+ */
+ public Person add(String name, String surname)
throws DAOException, IllegalArgumentException {
- try (final Connection conn = this.getConnection()) {
- final String query = "DELETE FROM people WHERE id=?";
+ if (name == null || surname == null) {
+ throw new IllegalArgumentException("name and surname can't be null");
+ }
+
+ try (Connection conn = this.getConnection()) {
+ final String query = "INSERT INTO people VALUES(null, ?, ?)";
- try (final PreparedStatement statement = conn.prepareStatement(query)) {
- statement.setInt(1, id);
+ try (PreparedStatement statement = conn.prepareStatement(query, Statement.RETURN_GENERATED_KEYS)) {
+ statement.setString(1, name);
+ statement.setString(2, surname);
- if (statement.executeUpdate() != 1) {
- throw new IllegalArgumentException("Invalid id");
+ if (statement.executeUpdate() == 1) {
+ try (ResultSet resultKeys = statement.getGeneratedKeys()) {
+ if (resultKeys.next()) {
+ return new Person(resultKeys.getInt(1), name, surname);
+ } else {
+ LOG.log(Level.SEVERE, "Error retrieving inserted id");
+ throw new SQLException("Error retrieving inserted id");
+ }
+ }
+ } else {
+ LOG.log(Level.SEVERE, "Error inserting value");
+ throw new SQLException("Error inserting value");
}
}
} catch (SQLException e) {
- LOG.log(Level.SEVERE, "Error deleting a person", e);
+ LOG.log(Level.SEVERE, "Error adding a person", e);
throw new DAOException(e);
}
}
- public Person modify(int id, String name, String surname)
+ /**
+ * Modifies a person previously persisted in the system. The person will be
+ * retrieved by the provided id and its current name and surname will be
+ * replaced with the provided.
+ *
+ * @param person a {@link Person} entity with the new data.
+ * @throws DAOException if an error happens while modifying the new person.
+ * @throws IllegalArgumentException if the person is {@code null}.
+ */
+ public void modify(Person person)
throws DAOException, IllegalArgumentException {
- if (name == null || surname == null) {
- throw new IllegalArgumentException("name and surname can't be null");
+ if (person == null) {
+ throw new IllegalArgumentException("person can't be null");
}
try (Connection conn = this.getConnection()) {
final String query = "UPDATE people SET name=?, surname=? WHERE id=?";
try (PreparedStatement statement = conn.prepareStatement(query)) {
- statement.setString(1, name);
- statement.setString(2, surname);
- statement.setInt(3, id);
+ statement.setString(1, person.getName());
+ statement.setString(2, person.getSurname());
+ statement.setInt(3, person.getId());
- if (statement.executeUpdate() == 1) {
- return new Person(id, name, surname);
- } else {
+ if (statement.executeUpdate() != 1) {
throw new IllegalArgumentException("name and surname can't be null");
}
}
@@ -110,36 +155,37 @@ public class PeopleDAO extends DAO {
}
}
- public Person add(String name, String surname)
+ /**
+ * Removes a persisted person from the system.
+ *
+ * @param id identifier of the person to be deleted.
+ * @throws DAOException if an error happens while deleting the person.
+ * @throws IllegalArgumentException if the provided id does not corresponds
+ * with any persisted person.
+ */
+ public void delete(int id)
throws DAOException, IllegalArgumentException {
- if (name == null || surname == null) {
- throw new IllegalArgumentException("name and surname can't be null");
- }
-
- try (Connection conn = this.getConnection()) {
- final String query = "INSERT INTO people VALUES(null, ?, ?)";
+ try (final Connection conn = this.getConnection()) {
+ final String query = "DELETE FROM people WHERE id=?";
- try (PreparedStatement statement = conn.prepareStatement(query, Statement.RETURN_GENERATED_KEYS)) {
- statement.setString(1, name);
- statement.setString(2, surname);
+ try (final PreparedStatement statement = conn.prepareStatement(query)) {
+ statement.setInt(1, id);
- if (statement.executeUpdate() == 1) {
- try (ResultSet resultKeys = statement.getGeneratedKeys()) {
- if (resultKeys.next()) {
- return new Person(resultKeys.getInt(1), name, surname);
- } else {
- LOG.log(Level.SEVERE, "Error retrieving inserted id");
- throw new SQLException("Error retrieving inserted id");
- }
- }
- } else {
- LOG.log(Level.SEVERE, "Error inserting value");
- throw new SQLException("Error inserting value");
+ if (statement.executeUpdate() != 1) {
+ throw new IllegalArgumentException("Invalid id");
}
}
} catch (SQLException e) {
- LOG.log(Level.SEVERE, "Error adding a person", e);
+ LOG.log(Level.SEVERE, "Error deleting a person", e);
throw new DAOException(e);
}
}
+
+ private Person rowToEntity(ResultSet row) throws SQLException {
+ return new Person(
+ row.getInt("id"),
+ row.getString("name"),
+ row.getString("surname")
+ );
+ }
}
diff --git a/src/main/java/es/uvigo/esei/daa/dao/UsersDAO.java b/src/main/java/es/uvigo/esei/daa/dao/UsersDAO.java
index 01460d9af2de6eba3be423733c258f7e6049cf9d..61ea8464f0c0c1b31aebd36c9bb9143fa0b16642 100644
--- a/src/main/java/es/uvigo/esei/daa/dao/UsersDAO.java
+++ b/src/main/java/es/uvigo/esei/daa/dao/UsersDAO.java
@@ -6,14 +6,33 @@ import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
-import java.util.Base64;
import java.util.logging.Level;
import java.util.logging.Logger;
+/**
+ * DAO class for managing the users of the system.
+ *
+ * @author Miguel Reboiro Jato
+ */
public class UsersDAO extends DAO {
- private final static Logger LOG = Logger.getLogger("UsersDAO");
+ private final static Logger LOG = Logger.getLogger(UsersDAO.class.getName());
- public String checkLogin(String login, String password) throws DAOException {
+ private final static String SALT = "daaexample-";
+
+ /**
+ * Checks if the provided credentials (login and password) correspond with a
+ * valid user registered in the system.
+ *
+ * The password is stored in the system "salted" and encoded with the
+ * SHA-256 algorithm.
+ *
+ * @param login the login of the user.
+ * @param password the password of the user.
+ * @return {@code true} if the credentials are valid. {@code false}
+ * otherwise.
+ * @throws DAOException if an error happens while checking the credentials.
+ */
+ public boolean checkLogin(String login, String password) throws DAOException {
try (final Connection conn = this.getConnection()) {
final String query = "SELECT password FROM users WHERE login=?";
@@ -23,15 +42,11 @@ public class UsersDAO extends DAO {
try (final ResultSet result = statement.executeQuery()) {
if (result.next()) {
final String dbPassword = result.getString("password");
- final String shaPassword = encodeSha256(password);
+ final String shaPassword = encodeSha256(SALT + password);
- if (shaPassword.equals(dbPassword)) {
- return encodeBase64(login + ":" + password);
- } else {
- return null;
- }
+ return shaPassword.equals(dbPassword);
} else {
- return null;
+ return false;
}
}
}
@@ -41,48 +56,6 @@ public class UsersDAO extends DAO {
}
}
- public String checkToken(String token)
- throws DAOException, IllegalArgumentException {
- final String decodedToken = decodeBase64(token);
- final int colonIndex = decodedToken.indexOf(':');
-
- if (colonIndex < 0 || colonIndex == decodedToken.length()-1) {
- throw new IllegalArgumentException("Invalid token");
- }
-
- final String login = decodedToken.substring(0, decodedToken.indexOf(':'));
- final String password = encodeSha256(decodedToken.substring(decodedToken.indexOf(':') + 1));
-
- try (final Connection conn = this.getConnection()) {
- final String query = "SELECT password FROM users WHERE login=?";
-
- try (final PreparedStatement statement = conn.prepareStatement(query)) {
- statement.setString(1, login);
-
- try (final ResultSet result = statement.executeQuery()) {
- if (result.next()) {
- final String dbPassword = result.getString("password");
-
- return password.equals(dbPassword) ? login : null;
- } else {
- return null;
- }
- }
- }
- } catch (SQLException e) {
- LOG.log(Level.SEVERE, "Error checking token", e);
- throw new DAOException(e);
- }
- }
-
- private final static String decodeBase64(String text) {
- return new String(Base64.getDecoder().decode(text.getBytes()));
- }
-
- private final static String encodeBase64(String text) {
- return Base64.getEncoder().encodeToString(text.getBytes());
- }
-
private final static String encodeSha256(String text) {
try {
final MessageDigest digest = MessageDigest.getInstance("SHA-256");
diff --git a/src/main/java/es/uvigo/esei/daa/entities/Person.java b/src/main/java/es/uvigo/esei/daa/entities/Person.java
index ae5c73fb346a10935ea1ea04b0a6e0e3730f0054..3df16c413d162b38bc5092b2f687e5255a2210bf 100644
--- a/src/main/java/es/uvigo/esei/daa/entities/Person.java
+++ b/src/main/java/es/uvigo/esei/daa/entities/Person.java
@@ -1,41 +1,78 @@
package es.uvigo.esei.daa.entities;
+import static java.util.Objects.requireNonNull;
+
+/**
+ * An entity that represents a person.
+ *
+ * @author Miguel Reboiro Jato
+ */
public class Person {
private int id;
private String name;
private String surname;
- public Person() {
- }
+ // Constructor needed for the JSON conversion
+ Person() {}
+ /**
+ * Constructs a new instance of {@link Person}.
+ *
+ * @param id identifier of the person.
+ * @param name name of the person.
+ * @param surname surname of the person.
+ */
public Person(int id, String name, String surname) {
this.id = id;
- this.name = name;
- this.surname = surname;
+ this.setName(name);
+ this.setSurname(surname);
}
+ /**
+ * Returns the identifier of the person.
+ *
+ * @return the identifier of the person.
+ */
public int getId() {
return id;
}
- public void setId(int id) {
- this.id = id;
- }
-
+ /**
+ * Returns the name of the person.
+ *
+ * @return the name of the person.
+ */
public String getName() {
return name;
}
+ /**
+ * Set the name of this person.
+ *
+ * @param name the new name of the person.
+ * @throws NullPointerException if the {@code name} is {@code null}.
+ */
public void setName(String name) {
- this.name = name;
+ this.name = requireNonNull(name, "Name can't be null");
}
+ /**
+ * Returns the surname of the person.
+ *
+ * @return the surname of the person.
+ */
public String getSurname() {
return surname;
}
+ /**
+ * Set the surname of this person.
+ *
+ * @param surname the new surname of the person.
+ * @throws NullPointerException if the {@code surname} is {@code null}.
+ */
public void setSurname(String surname) {
- this.surname = surname;
+ this.surname = requireNonNull(surname, "Surname can't be null");
}
@Override
@@ -43,8 +80,6 @@ public class Person {
final int prime = 31;
int result = 1;
result = prime * result + id;
- result = prime * result + ((name == null) ? 0 : name.hashCode());
- result = prime * result + ((surname == null) ? 0 : surname.hashCode());
return result;
}
@@ -59,16 +94,6 @@ public class Person {
Person other = (Person) obj;
if (id != other.id)
return false;
- if (name == null) {
- if (other.name != null)
- return false;
- } else if (!name.equals(other.name))
- return false;
- if (surname == null) {
- if (other.surname != null)
- return false;
- } else if (!surname.equals(other.surname))
- return false;
return true;
}
}
diff --git a/src/main/java/es/uvigo/esei/daa/rest/PeopleResource.java b/src/main/java/es/uvigo/esei/daa/rest/PeopleResource.java
index 9d69d300c463f766a4f8f95a5c611a77fd852360..09b8834c7b71d5176e012bcd6076d36eb275bb29 100644
--- a/src/main/java/es/uvigo/esei/daa/rest/PeopleResource.java
+++ b/src/main/java/es/uvigo/esei/daa/rest/PeopleResource.java
@@ -16,69 +16,130 @@ import javax.ws.rs.core.Response;
import es.uvigo.esei.daa.dao.DAOException;
import es.uvigo.esei.daa.dao.PeopleDAO;
+import es.uvigo.esei.daa.entities.Person;
+/**
+ * REST resource for managing people.
+ *
+ * @author Miguel Reboiro Jato.
+ */
@Path("/people")
@Produces(MediaType.APPLICATION_JSON)
public class PeopleResource {
- private final static Logger LOG = Logger.getLogger("PeopleResource");
+ private final static Logger LOG = Logger.getLogger(PeopleResource.class.getName());
private final PeopleDAO dao;
+ /**
+ * Constructs a new instance of {@link PeopleResource}.
+ */
public PeopleResource() {
this(new PeopleDAO());
}
- // For testing purposes
+ // Needed for testing purposes
PeopleResource(PeopleDAO dao) {
this.dao = dao;
}
-
- @GET
- public Response list() {
- try {
- return Response.ok(this.dao.list()).build();
- } catch (DAOException e) {
- LOG.log(Level.SEVERE, "Error listing people", e);
- return Response.serverError().entity(e.getMessage()).build();
- }
- }
+ /**
+ * Returns a person with the provided identifier.
+ *
+ * @param id the identifier of the person to retrieve.
+ * @return a 200 OK response with a person that has the provided identifier.
+ * If the identifier does not corresponds with any user, a 400 Bad Request
+ * response with an error message will be returned. If an error happens
+ * while retrieving the list, a 500 Internal Server Error response with an
+ * error message will be returned.
+ */
@GET
@Path("/{id}")
public Response get(
@PathParam("id") int id
) {
try {
- return Response.ok(this.dao.get(id), MediaType.APPLICATION_JSON).build();
+ final Person person = this.dao.get(id);
+
+ return Response.ok(person).build();
} catch (IllegalArgumentException iae) {
LOG.log(Level.FINE, "Invalid person id in get method", iae);
+
return Response.status(Response.Status.BAD_REQUEST)
- .entity(iae.getMessage()).build();
+ .entity(iae.getMessage())
+ .build();
} catch (DAOException e) {
LOG.log(Level.SEVERE, "Error getting a person", e);
+
+ return Response.serverError()
+ .entity(e.getMessage())
+ .build();
+ }
+ }
+
+ /**
+ * Returns the complete list of people stored in the system.
+ *
+ * @return a 200 OK response with the complete list of people stored in the
+ * system. If an error happens while retrieving the list, a 500 Internal
+ * Server Error response with an error message will be returned.
+ */
+ @GET
+ public Response list() {
+ try {
+ return Response.ok(this.dao.list()).build();
+ } catch (DAOException e) {
+ LOG.log(Level.SEVERE, "Error listing people", e);
return Response.serverError().entity(e.getMessage()).build();
}
}
- @DELETE
- @Path("/{id}")
- public Response delete(
- @PathParam("id") int id
+ /**
+ * Creates a new person in the system.
+ *
+ * @param name the name of the new person.
+ * @param surname the surname of the new person.
+ * @return a 200 OK response with a person that has been created. If the
+ * name or the surname are not provided, a 400 Bad Request response with an
+ * error message will be returned. If an error happens while retrieving the
+ * list, a 500 Internal Server Error response with an error message will be
+ * returned.
+ */
+ @POST
+ public Response add(
+ @FormParam("name") String name,
+ @FormParam("surname") String surname
) {
try {
- this.dao.delete(id);
+ final Person newPerson = this.dao.add(name, surname);
- return Response.ok(id).build();
+ return Response.ok(newPerson).build();
} catch (IllegalArgumentException iae) {
- LOG.log(Level.FINE, "Invalid person id in delete method", iae);
+ LOG.log(Level.FINE, "Invalid person id in add method", iae);
+
return Response.status(Response.Status.BAD_REQUEST)
- .entity(iae.getMessage()).build();
+ .entity(iae.getMessage())
+ .build();
} catch (DAOException e) {
- LOG.log(Level.SEVERE, "Error deleting a person", e);
- return Response.serverError().entity(e.getMessage()).build();
+ LOG.log(Level.SEVERE, "Error adding a person", e);
+
+ return Response.serverError()
+ .entity(e.getMessage())
+ .build();
}
}
-
+
+ /**
+ * Modifies the data of a person.
+ *
+ * @param id identifier of the person to modify.
+ * @param name the new name of the person.
+ * @param surname the new surname of the person.
+ * @return a 200 OK response with a person that has been modified. If the
+ * identifier does not corresponds with any user or the name or surname are
+ * not provided, a 400 Bad Request response with an error message will be
+ * returned. If an error happens while retrieving the list, a 500 Internal
+ * Server Error response with an error message will be returned.
+ */
@PUT
@Path("/{id}")
public Response modify(
@@ -87,31 +148,64 @@ public class PeopleResource {
@FormParam("surname") String surname
) {
try {
- return Response.ok(this.dao.modify(id, name, surname)).build();
+ final Person modifiedPerson = new Person(id, name, surname);
+ this.dao.modify(modifiedPerson);
+
+ return Response.ok(modifiedPerson).build();
+ } catch (NullPointerException npe) {
+ final String message = String.format("Invalid data for person (name: %s, surname: %s)", name, surname);
+
+ LOG.log(Level.FINE, message);
+
+ return Response.status(Response.Status.BAD_REQUEST)
+ .entity(message)
+ .build();
} catch (IllegalArgumentException iae) {
LOG.log(Level.FINE, "Invalid person id in modify method", iae);
+
return Response.status(Response.Status.BAD_REQUEST)
- .entity(iae.getMessage()).build();
+ .entity(iae.getMessage())
+ .build();
} catch (DAOException e) {
LOG.log(Level.SEVERE, "Error modifying a person", e);
- return Response.serverError().entity(e.getMessage()).build();
+
+ return Response.serverError()
+ .entity(e.getMessage())
+ .build();
}
}
-
- @POST
- public Response add(
- @FormParam("name") String name,
- @FormParam("surname") String surname
+
+ /**
+ * Deletes a person from the system.
+ *
+ * @param id the identifier of the person to be deleted.
+ * @return a 200 OK response with the identifier of the person that has
+ * been deleted. If the identifier does not corresponds with any user, a 400
+ * Bad Request response with an error message will be returned. If an error
+ * happens while retrieving the list, a 500 Internal Server Error response
+ * with an error message will be returned.
+ */
+ @DELETE
+ @Path("/{id}")
+ public Response delete(
+ @PathParam("id") int id
) {
try {
- return Response.ok(this.dao.add(name, surname)).build();
+ this.dao.delete(id);
+
+ return Response.ok(id).build();
} catch (IllegalArgumentException iae) {
- LOG.log(Level.FINE, "Invalid person id in add method", iae);
+ LOG.log(Level.FINE, "Invalid person id in delete method", iae);
+
return Response.status(Response.Status.BAD_REQUEST)
- .entity(iae.getMessage()).build();
+ .entity(iae.getMessage())
+ .build();
} catch (DAOException e) {
- LOG.log(Level.SEVERE, "Error adding a person", e);
- return Response.serverError().entity(e.getMessage()).build();
+ LOG.log(Level.SEVERE, "Error deleting a person", e);
+
+ return Response.serverError()
+ .entity(e.getMessage())
+ .build();
}
}
}
diff --git a/src/main/webapp/META-INF/context.xml b/src/main/webapp/META-INF/context.xml
deleted file mode 100644
index 35bc2a76c7895ab4805dd6adb71fa848af3409a4..0000000000000000000000000000000000000000
--- a/src/main/webapp/META-INF/context.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/src/main/webapp/WEB-INF/web.xml b/src/main/webapp/WEB-INF/web.xml
index cc0a77fd28856b853b76cf6d1082f27e4583e6fa..f75cc40fb869362880bd9d5d66a911e829ce6790 100644
--- a/src/main/webapp/WEB-INF/web.xml
+++ b/src/main/webapp/WEB-INF/web.xml
@@ -1,23 +1,12 @@
-
+
DAAExample
index.html
- index.htm
- index.jsp
- default.html
- default.htm
- default.jsp
-
-
- DAA Example DB Connection
- jdbc/daaexample
- javax.sql.DataSource
- Container
-
\ No newline at end of file
diff --git a/src/main/webapp/index.html b/src/main/webapp/index.html
index 87a10ae81d9dafc2c6d4dfbfd59115c261ffd76a..a688425bd7cdd100847d70fdf17e0ec12d227263 100644
--- a/src/main/webapp/index.html
+++ b/src/main/webapp/index.html
@@ -6,9 +6,15 @@