Mon, 11 May 2020 19:09:06 +0200
adds DAO for Project entity and save/update methods
1.1 --- a/src/main/java/de/uapcore/lightpit/AbstractLightPITServlet.java Sun May 10 10:58:31 2020 +0200 1.2 +++ b/src/main/java/de/uapcore/lightpit/AbstractLightPITServlet.java Mon May 11 19:09:06 2020 +0200 1.3 @@ -28,6 +28,8 @@ 1.4 */ 1.5 package de.uapcore.lightpit; 1.6 1.7 +import de.uapcore.lightpit.dao.DataAccessObjects; 1.8 +import de.uapcore.lightpit.dao.postgres.PGDataAccessObjects; 1.9 import org.slf4j.Logger; 1.10 import org.slf4j.LoggerFactory; 1.11 1.12 @@ -39,6 +41,8 @@ 1.13 import java.io.IOException; 1.14 import java.lang.reflect.Method; 1.15 import java.lang.reflect.Modifier; 1.16 +import java.sql.Connection; 1.17 +import java.sql.SQLException; 1.18 import java.util.*; 1.19 1.20 /** 1.21 @@ -59,7 +63,7 @@ 1.22 1.23 @FunctionalInterface 1.24 private interface HandlerMethod { 1.25 - ResponseType apply(HttpServletRequest t, HttpServletResponse u) throws IOException; 1.26 + ResponseType apply(HttpServletRequest request, HttpServletResponse response, DataAccessObjects dao) throws IOException, SQLException; 1.27 } 1.28 1.29 /** 1.30 @@ -82,21 +86,30 @@ 1.31 return (ModuleManager) getServletContext().getAttribute(ModuleManager.SC_ATTR_NAME); 1.32 } 1.33 1.34 + 1.35 /** 1.36 - * Gives implementing modules access to the {@link DatabaseFacade}. 1.37 + * Creates a set of data access objects for the specified connection. 1.38 * 1.39 - * @return the database facade 1.40 + * @param connection the SQL connection 1.41 + * @return a set of data access objects 1.42 */ 1.43 - protected final DatabaseFacade getDatabaseFacade() { 1.44 - return (DatabaseFacade) getServletContext().getAttribute(DatabaseFacade.SC_ATTR_NAME); 1.45 + private DataAccessObjects createDataAccessObjects(Connection connection) throws SQLException { 1.46 + final var df = (DatabaseFacade) getServletContext().getAttribute(DatabaseFacade.SC_ATTR_NAME); 1.47 + switch (df.getSQLDialect()) { 1.48 + case Postgres: 1.49 + return new PGDataAccessObjects(connection); 1.50 + default: 1.51 + throw new AssertionError("Non-exhaustive switch - this is a bug."); 1.52 + } 1.53 } 1.54 1.55 - private ResponseType invokeMapping(Method method, HttpServletRequest req, HttpServletResponse resp) throws IOException { 1.56 + private ResponseType invokeMapping(Method method, HttpServletRequest req, HttpServletResponse resp, DataAccessObjects dao) throws IOException { 1.57 try { 1.58 LOG.trace("invoke {}#{}", method.getDeclaringClass().getName(), method.getName()); 1.59 - return (ResponseType) method.invoke(this, req, resp); 1.60 + return (ResponseType) method.invoke(this, req, resp, dao); 1.61 } catch (ReflectiveOperationException | ClassCastException ex) { 1.62 - LOG.error(String.format("invocation of method %s failed", method.getName()), ex); 1.63 + LOG.error("invocation of method {} failed: {}", method.getName(), ex.getMessage()); 1.64 + LOG.debug("Details: ", ex); 1.65 resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); 1.66 return ResponseType.NONE; 1.67 } 1.68 @@ -140,15 +153,16 @@ 1.69 } 1.70 1.71 Class<?>[] params = method.getParameterTypes(); 1.72 - if (params.length == 2 1.73 + if (params.length == 3 1.74 && HttpServletRequest.class.isAssignableFrom(params[0]) 1.75 - && HttpServletResponse.class.isAssignableFrom(params[1])) { 1.76 + && HttpServletResponse.class.isAssignableFrom(params[1]) 1.77 + && DataAccessObjects.class.isAssignableFrom(params[2])) { 1.78 1.79 final String requestPath = "/" + mapping.get().requestPath(); 1.80 1.81 if (mappings.computeIfAbsent(mapping.get().method(), k -> new HashMap<>()). 1.82 putIfAbsent(requestPath, 1.83 - (req, resp) -> invokeMapping(method, req, resp)) != null) { 1.84 + (req, resp, dao) -> invokeMapping(method, req, resp, dao)) != null) { 1.85 LOG.warn("{} {} has multiple mappings", 1.86 mapping.get().method(), 1.87 mapping.get().requestPath() 1.88 @@ -238,8 +252,7 @@ 1.89 } 1.90 } 1.91 1.92 - private void doProcess(HttpMethod method, HttpServletRequest req, HttpServletResponse resp) 1.93 - throws ServletException, IOException { 1.94 + private void doProcess(HttpMethod method, HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 1.95 1.96 // choose the requested language as session language (if available) or fall back to english, otherwise 1.97 HttpSession session = req.getSession(); 1.98 @@ -260,13 +273,21 @@ 1.99 req.setAttribute(Constants.REQ_ATTR_MODULE_CLASSNAME, this.getClass().getName()); 1.100 Optional.ofNullable(moduleInfo).ifPresent((proxy) -> req.setAttribute(Constants.REQ_ATTR_MODULE_INFO, proxy)); 1.101 1.102 - 1.103 - // call the handler, if available, or send an HTTP 404 error 1.104 - Optional<HandlerMethod> mapping = findMapping(method, req); 1.105 - if (mapping.isPresent()) { 1.106 - forwardAsSpecified(mapping.get().apply(req, resp), req, resp); 1.107 - } else { 1.108 - resp.sendError(HttpServletResponse.SC_NOT_FOUND); 1.109 + // obtain a connection and create the data access objects 1.110 + final var db = (DatabaseFacade) req.getServletContext().getAttribute(DatabaseFacade.SC_ATTR_NAME); 1.111 + try (final var connection = db.getDataSource().getConnection()) { 1.112 + final var dao = createDataAccessObjects(connection); 1.113 + // call the handler, if available, or send an HTTP 404 error 1.114 + final var mapping = findMapping(method, req); 1.115 + if (mapping.isPresent()) { 1.116 + forwardAsSpecified(mapping.get().apply(req, resp, dao), req, resp); 1.117 + } else { 1.118 + resp.sendError(HttpServletResponse.SC_NOT_FOUND); 1.119 + } 1.120 + } catch (SQLException ex) { 1.121 + LOG.error("Database exception (Code {}): {}", ex.getErrorCode(), ex.getMessage()); 1.122 + LOG.debug("Details: ", ex); 1.123 + resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Database Error - Code:" + ex.getErrorCode()); 1.124 } 1.125 } 1.126
2.1 --- a/src/main/java/de/uapcore/lightpit/DatabaseFacade.java Sun May 10 10:58:31 2020 +0200 2.2 +++ b/src/main/java/de/uapcore/lightpit/DatabaseFacade.java Mon May 11 19:09:06 2020 +0200 2.3 @@ -28,8 +28,6 @@ 2.4 */ 2.5 package de.uapcore.lightpit; 2.6 2.7 -import de.uapcore.lightpit.dao.DataAccessObjects; 2.8 -import de.uapcore.lightpit.dao.postgres.PGDataAccessObjects; 2.9 import org.slf4j.Logger; 2.10 import org.slf4j.LoggerFactory; 2.11 2.12 @@ -91,29 +89,14 @@ 2.13 2.14 private static final String DS_JNDI_NAME = "jdbc/lightpit/app"; 2.15 private DataSource dataSource; 2.16 - private DataAccessObjects dataAccessObjects; 2.17 2.18 /** 2.19 * Returns the data source. 2.20 - * <p> 2.21 - * The Optional returned should never be empty. However, if something goes 2.22 - * wrong during initialization, the data source might be absent. 2.23 - * Hence, users of this data source are forced to check the existence. 2.24 * 2.25 * @return a data source 2.26 */ 2.27 - public Optional<DataSource> getDataSource() { 2.28 - // TODO: this should not be an optional, if an empty optional is actually an exception 2.29 - return Optional.ofNullable(dataSource); 2.30 - } 2.31 - 2.32 - /** 2.33 - * Returns the data access objects. 2.34 - * 2.35 - * @return an interface to obtain the data access objects 2.36 - */ 2.37 - public DataAccessObjects getDataAccessObjects() { 2.38 - return dataAccessObjects; 2.39 + public DataSource getDataSource() { 2.40 + return dataSource; 2.41 } 2.42 2.43 public Dialect getSQLDialect() { 2.44 @@ -171,8 +154,6 @@ 2.45 } 2.46 } 2.47 2.48 - dataAccessObjects = createDataAccessObjects(dialect); 2.49 - 2.50 try { 2.51 LOG.debug("Trying to access JNDI context {}...", contextName); 2.52 Context initialCtx = new InitialContext(); 2.53 @@ -191,15 +172,6 @@ 2.54 LOG.info("Database facade injected into ServletContext."); 2.55 } 2.56 2.57 - private static DataAccessObjects createDataAccessObjects(Dialect dialect) { 2.58 - switch (dialect) { 2.59 - case Postgres: 2.60 - return new PGDataAccessObjects(); 2.61 - default: 2.62 - throw new AssertionError("Non-exhaustive switch - this is a bug."); 2.63 - } 2.64 - } 2.65 - 2.66 @Override 2.67 public void contextDestroyed(ServletContextEvent sce) { 2.68 dataSource = null;
3.1 --- a/src/main/java/de/uapcore/lightpit/dao/AbstractDao.java Sun May 10 10:58:31 2020 +0200 3.2 +++ b/src/main/java/de/uapcore/lightpit/dao/AbstractDao.java Mon May 11 19:09:06 2020 +0200 3.3 @@ -28,24 +28,65 @@ 3.4 */ 3.5 package de.uapcore.lightpit.dao; 3.6 3.7 -import java.sql.Connection; 3.8 import java.sql.PreparedStatement; 3.9 import java.sql.ResultSet; 3.10 import java.sql.SQLException; 3.11 +import java.sql.Types; 3.12 import java.util.ArrayList; 3.13 import java.util.List; 3.14 +import java.util.Optional; 3.15 +import java.util.function.Function; 3.16 3.17 public abstract class AbstractDao<T> implements GenericDao<T> { 3.18 3.19 - protected abstract PreparedStatement listQuery(Connection connection) throws SQLException; 3.20 + private final PreparedStatement listQuery; 3.21 3.22 - protected abstract T mapColumns(ResultSet result) throws SQLException; 3.23 + protected AbstractDao(PreparedStatement listQuery) { 3.24 + this.listQuery = listQuery; 3.25 + } 3.26 + 3.27 + public final T mapColumns(ResultSet result) throws SQLException { 3.28 + return mapColumns(result, ""); 3.29 + } 3.30 + 3.31 + public abstract T mapColumns(ResultSet result, String qualifier) throws SQLException; 3.32 + 3.33 + /** 3.34 + * Qualifies a column label if an qualifier is specified. 3.35 + * 3.36 + * @param qualifier an optional qualifier 3.37 + * @param label the column label 3.38 + * @return the label, qualified if necessary 3.39 + */ 3.40 + protected final String qual(String qualifier, String label) { 3.41 + if (qualifier == null || qualifier.isBlank()) { 3.42 + return label; 3.43 + } else { 3.44 + return qualifier + "." + label; 3.45 + } 3.46 + } 3.47 + 3.48 + protected final void setStringOrNull(PreparedStatement stmt, int index, String str) throws SQLException { 3.49 + if (str == null || str.isBlank()) { 3.50 + stmt.setNull(index, Types.VARCHAR); 3.51 + } else { 3.52 + stmt.setString(index, str); 3.53 + } 3.54 + } 3.55 + 3.56 + protected final <T> void setForeignKeyOrNull(PreparedStatement stmt, int index, T instance, Function<T, Integer> keyGetter) throws SQLException { 3.57 + Integer key = Optional.ofNullable(instance).map(keyGetter).orElse(null); 3.58 + if (key == null) { 3.59 + stmt.setNull(index, Types.INTEGER); 3.60 + } else { 3.61 + stmt.setInt(index, key); 3.62 + } 3.63 + } 3.64 3.65 @Override 3.66 - public List<T> list(Connection conn) throws SQLException { 3.67 + public List<T> list() throws SQLException { 3.68 List<T> list = new ArrayList<>(); 3.69 - try (PreparedStatement stmt = listQuery(conn); 3.70 - ResultSet result = stmt.executeQuery()) { 3.71 + try (ResultSet result = listQuery.executeQuery()) { 3.72 while (result.next()) { 3.73 list.add(mapColumns(result)); 3.74 }
4.1 --- a/src/main/java/de/uapcore/lightpit/dao/DataAccessObjects.java Sun May 10 10:58:31 2020 +0200 4.2 +++ b/src/main/java/de/uapcore/lightpit/dao/DataAccessObjects.java Mon May 11 19:09:06 2020 +0200 4.3 @@ -30,4 +30,6 @@ 4.4 4.5 public interface DataAccessObjects { 4.6 UserDao getUserDao(); 4.7 + 4.8 + ProjectDao getProjectDao(); 4.9 }
5.1 --- a/src/main/java/de/uapcore/lightpit/dao/GenericDao.java Sun May 10 10:58:31 2020 +0200 5.2 +++ b/src/main/java/de/uapcore/lightpit/dao/GenericDao.java Mon May 11 19:09:06 2020 +0200 5.3 @@ -28,7 +28,6 @@ 5.4 */ 5.5 package de.uapcore.lightpit.dao; 5.6 5.7 -import java.sql.Connection; 5.8 import java.sql.SQLException; 5.9 import java.util.List; 5.10 5.11 @@ -36,9 +35,38 @@ 5.12 /** 5.13 * Returns a list of all entities. 5.14 * 5.15 - * @param connection conn the connection to use 5.16 * @return a list of all objects 5.17 * @throws SQLException on any kind of SQL errors 5.18 */ 5.19 - List<T> list(Connection connection) throws SQLException; 5.20 + List<T> list() throws SQLException; 5.21 + 5.22 + /** 5.23 + * Inserts an instance into database. 5.24 + * 5.25 + * @param instance the instance to insert 5.26 + * @throws SQLException on any kind of SQL errors 5.27 + */ 5.28 + void save(T instance) throws SQLException; 5.29 + 5.30 + /** 5.31 + * Updates an instance in the database. 5.32 + * 5.33 + * @param instance the instance to insert 5.34 + * @return true if an instance has been updated, false if no instance with the specified ID was found 5.35 + * @throws SQLException on any kind of SQL errors 5.36 + */ 5.37 + boolean update(T instance) throws SQLException; 5.38 + 5.39 + /** 5.40 + * Inserts or updates an instance in the database. 5.41 + * Tries an update first and if that fails, performs a save. 5.42 + * 5.43 + * @param instance the instance to insert or update 5.44 + * @throws SQLException on any kind of SQL errors 5.45 + * @see #update(Object) 5.46 + * @see #save(Object) 5.47 + */ 5.48 + default void saveOrUpdate(T instance) throws SQLException { 5.49 + if (!update(instance)) save(instance); 5.50 + } 5.51 }
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 6.2 +++ b/src/main/java/de/uapcore/lightpit/dao/ProjectDao.java Mon May 11 19:09:06 2020 +0200 6.3 @@ -0,0 +1,34 @@ 6.4 +/* 6.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 6.6 + * 6.7 + * Copyright 2018 Mike Becker. All rights reserved. 6.8 + * 6.9 + * Redistribution and use in source and binary forms, with or without 6.10 + * modification, are permitted provided that the following conditions are met: 6.11 + * 6.12 + * 1. Redistributions of source code must retain the above copyright 6.13 + * notice, this list of conditions and the following disclaimer. 6.14 + * 6.15 + * 2. Redistributions in binary form must reproduce the above copyright 6.16 + * notice, this list of conditions and the following disclaimer in the 6.17 + * documentation and/or other materials provided with the distribution. 6.18 + * 6.19 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 6.20 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 6.21 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 6.22 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 6.23 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 6.24 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 6.25 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 6.26 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 6.27 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 6.28 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 6.29 + * POSSIBILITY OF SUCH DAMAGE. 6.30 + * 6.31 + */ 6.32 +package de.uapcore.lightpit.dao; 6.33 + 6.34 +import de.uapcore.lightpit.entities.Project; 6.35 + 6.36 +public interface ProjectDao extends GenericDao<Project> { 6.37 +}
7.1 --- a/src/main/java/de/uapcore/lightpit/dao/postgres/PGDataAccessObjects.java Sun May 10 10:58:31 2020 +0200 7.2 +++ b/src/main/java/de/uapcore/lightpit/dao/postgres/PGDataAccessObjects.java Mon May 11 19:09:06 2020 +0200 7.3 @@ -29,14 +29,30 @@ 7.4 package de.uapcore.lightpit.dao.postgres; 7.5 7.6 import de.uapcore.lightpit.dao.DataAccessObjects; 7.7 +import de.uapcore.lightpit.dao.ProjectDao; 7.8 import de.uapcore.lightpit.dao.UserDao; 7.9 7.10 +import java.sql.Connection; 7.11 +import java.sql.SQLException; 7.12 + 7.13 public class PGDataAccessObjects implements DataAccessObjects { 7.14 7.15 - private final UserDao userDao = new PGUserDao(); 7.16 + private final UserDao userDao; 7.17 + private final ProjectDao projectDao; 7.18 + 7.19 + public PGDataAccessObjects(Connection connection) throws SQLException { 7.20 + final PGUserDao pgUserDao = new PGUserDao(connection); 7.21 + userDao = pgUserDao; 7.22 + projectDao = new PGProjectDao(connection, pgUserDao); 7.23 + } 7.24 7.25 @Override 7.26 public UserDao getUserDao() { 7.27 return userDao; 7.28 } 7.29 + 7.30 + @Override 7.31 + public ProjectDao getProjectDao() { 7.32 + return projectDao; 7.33 + } 7.34 }
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 8.2 +++ b/src/main/java/de/uapcore/lightpit/dao/postgres/PGProjectDao.java Mon May 11 19:09:06 2020 +0200 8.3 @@ -0,0 +1,92 @@ 8.4 +/* 8.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 8.6 + * 8.7 + * Copyright 2018 Mike Becker. All rights reserved. 8.8 + * 8.9 + * Redistribution and use in source and binary forms, with or without 8.10 + * modification, are permitted provided that the following conditions are met: 8.11 + * 8.12 + * 1. Redistributions of source code must retain the above copyright 8.13 + * notice, this list of conditions and the following disclaimer. 8.14 + * 8.15 + * 2. Redistributions in binary form must reproduce the above copyright 8.16 + * notice, this list of conditions and the following disclaimer in the 8.17 + * documentation and/or other materials provided with the distribution. 8.18 + * 8.19 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 8.20 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 8.21 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 8.22 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 8.23 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 8.24 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 8.25 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 8.26 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 8.27 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 8.28 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 8.29 + * POSSIBILITY OF SUCH DAMAGE. 8.30 + * 8.31 + */ 8.32 +package de.uapcore.lightpit.dao.postgres; 8.33 + 8.34 +import de.uapcore.lightpit.dao.AbstractDao; 8.35 +import de.uapcore.lightpit.dao.ProjectDao; 8.36 +import de.uapcore.lightpit.entities.Project; 8.37 +import de.uapcore.lightpit.entities.User; 8.38 + 8.39 +import java.sql.Connection; 8.40 +import java.sql.PreparedStatement; 8.41 +import java.sql.ResultSet; 8.42 +import java.sql.SQLException; 8.43 +import java.util.Objects; 8.44 + 8.45 +public final class PGProjectDao extends AbstractDao<Project> implements ProjectDao { 8.46 + 8.47 + private final PGUserDao userDao; 8.48 + 8.49 + private final PreparedStatement insert; 8.50 + private final PreparedStatement update; 8.51 + 8.52 + public PGProjectDao(Connection connection, PGUserDao userDao) throws SQLException { 8.53 + super(connection.prepareStatement( 8.54 + "select * from lpit_project join lpit_user owner on lpit_project.owner = owner.userid")); 8.55 + 8.56 + insert = connection.prepareStatement( 8.57 + "insert into lpit_project (name, description, repourl, owner) values (?, ?, ?, ?)" 8.58 + ); 8.59 + update = connection.prepareStatement( 8.60 + "update lpit_project set name = ?, description = ?, repourl = ?, owner = ? where id = ?" 8.61 + ); 8.62 + 8.63 + this.userDao = userDao; 8.64 + } 8.65 + 8.66 + @Override 8.67 + public Project mapColumns(ResultSet result, String q) throws SQLException { 8.68 + final var proj = new Project(result.getInt(qual(q, "id"))); 8.69 + proj.setName(result.getString(qual(q, "name"))); 8.70 + proj.setDescription(result.getString(qual(q, "description"))); 8.71 + proj.setRepoUrl(result.getString(qual(q, "repourl"))); 8.72 + proj.setOwner(userDao.mapColumns(result, "owner")); 8.73 + return proj; 8.74 + } 8.75 + 8.76 + @Override 8.77 + public void save(Project instance) throws SQLException { 8.78 + Objects.requireNonNull(instance.getName()); 8.79 + insert.setString(1, instance.getName()); 8.80 + setStringOrNull(insert, 2, instance.getDescription()); 8.81 + setStringOrNull(insert, 3, instance.getRepoUrl()); 8.82 + setForeignKeyOrNull(insert, 4, instance.getOwner(), User::getUserID); 8.83 + insert.executeUpdate(); 8.84 + } 8.85 + 8.86 + @Override 8.87 + public boolean update(Project instance) throws SQLException { 8.88 + Objects.requireNonNull(instance.getName()); 8.89 + update.setString(1, instance.getName()); 8.90 + setStringOrNull(update, 2, instance.getDescription()); 8.91 + setStringOrNull(update, 3, instance.getRepoUrl()); 8.92 + setForeignKeyOrNull(update, 4, instance.getOwner(), User::getUserID); 8.93 + return update.executeUpdate() > 0; 8.94 + } 8.95 +}
9.1 --- a/src/main/java/de/uapcore/lightpit/dao/postgres/PGUserDao.java Sun May 10 10:58:31 2020 +0200 9.2 +++ b/src/main/java/de/uapcore/lightpit/dao/postgres/PGUserDao.java Mon May 11 19:09:06 2020 +0200 9.3 @@ -36,20 +36,45 @@ 9.4 import java.sql.PreparedStatement; 9.5 import java.sql.ResultSet; 9.6 import java.sql.SQLException; 9.7 +import java.util.Objects; 9.8 9.9 public final class PGUserDao extends AbstractDao<User> implements UserDao { 9.10 9.11 + private final PreparedStatement insert; 9.12 + private final PreparedStatement update; 9.13 + 9.14 + public PGUserDao(Connection connection) throws SQLException { 9.15 + super(connection.prepareStatement("select * from lpit_user where userid >= 0 order by username")); 9.16 + 9.17 + insert = connection.prepareStatement("insert into lpit_user (username, lastname, givenname, mail) values (?, ?, ?, ?)"); 9.18 + update = connection.prepareStatement("update lpit_user set lastname = ?, givenname = ?, mail = ? where userid = ?"); 9.19 + } 9.20 + 9.21 @Override 9.22 - protected User mapColumns(ResultSet result) throws SQLException { 9.23 - final var user = new User(result.getInt("userid")); 9.24 - user.setUsername(result.getString("username")); 9.25 - user.setGivenname(result.getString("givenname")); 9.26 - user.setLastname(result.getString("lastname")); 9.27 + public User mapColumns(ResultSet result, String q) throws SQLException { 9.28 + final var user = new User(result.getInt(qual(q, "userid"))); 9.29 + user.setUsername(result.getString(qual(q, "username"))); 9.30 + user.setGivenname(result.getString(qual(q, "givenname"))); 9.31 + user.setLastname(result.getString(qual(q, "lastname"))); 9.32 return user; 9.33 } 9.34 9.35 @Override 9.36 - protected PreparedStatement listQuery(Connection conn) throws SQLException { 9.37 - return conn.prepareStatement("select * from lpit_user where userid >= 0 order by username"); 9.38 + public void save(User instance) throws SQLException { 9.39 + Objects.requireNonNull(instance.getUsername()); 9.40 + insert.setString(1, instance.getUsername()); 9.41 + setStringOrNull(insert, 2, instance.getLastname()); 9.42 + setStringOrNull(insert, 3, instance.getGivenname()); 9.43 + setStringOrNull(insert, 4, instance.getMail()); 9.44 + insert.executeUpdate(); 9.45 + } 9.46 + 9.47 + @Override 9.48 + public boolean update(User instance) throws SQLException { 9.49 + setStringOrNull(update, 1, instance.getLastname()); 9.50 + setStringOrNull(update, 2, instance.getGivenname()); 9.51 + setStringOrNull(update, 3, instance.getMail()); 9.52 + update.setInt(4, instance.getUserID()); 9.53 + return update.executeUpdate() > 0; 9.54 } 9.55 }
10.1 --- a/src/main/java/de/uapcore/lightpit/entities/Project.java Sun May 10 10:58:31 2020 +0200 10.2 +++ b/src/main/java/de/uapcore/lightpit/entities/Project.java Mon May 11 19:09:06 2020 +0200 10.3 @@ -1,3 +1,31 @@ 10.4 +/* 10.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 10.6 + * 10.7 + * Copyright 2018 Mike Becker. All rights reserved. 10.8 + * 10.9 + * Redistribution and use in source and binary forms, with or without 10.10 + * modification, are permitted provided that the following conditions are met: 10.11 + * 10.12 + * 1. Redistributions of source code must retain the above copyright 10.13 + * notice, this list of conditions and the following disclaimer. 10.14 + * 10.15 + * 2. Redistributions in binary form must reproduce the above copyright 10.16 + * notice, this list of conditions and the following disclaimer in the 10.17 + * documentation and/or other materials provided with the distribution. 10.18 + * 10.19 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 10.20 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 10.21 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 10.22 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 10.23 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 10.24 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 10.25 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 10.26 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 10.27 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 10.28 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 10.29 + * POSSIBILITY OF SUCH DAMAGE. 10.30 + * 10.31 + */ 10.32 package de.uapcore.lightpit.entities; 10.33 10.34 import java.util.ArrayList;
11.1 --- a/src/main/java/de/uapcore/lightpit/entities/Version.java Sun May 10 10:58:31 2020 +0200 11.2 +++ b/src/main/java/de/uapcore/lightpit/entities/Version.java Mon May 11 19:09:06 2020 +0200 11.3 @@ -1,3 +1,31 @@ 11.4 +/* 11.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 11.6 + * 11.7 + * Copyright 2018 Mike Becker. All rights reserved. 11.8 + * 11.9 + * Redistribution and use in source and binary forms, with or without 11.10 + * modification, are permitted provided that the following conditions are met: 11.11 + * 11.12 + * 1. Redistributions of source code must retain the above copyright 11.13 + * notice, this list of conditions and the following disclaimer. 11.14 + * 11.15 + * 2. Redistributions in binary form must reproduce the above copyright 11.16 + * notice, this list of conditions and the following disclaimer in the 11.17 + * documentation and/or other materials provided with the distribution. 11.18 + * 11.19 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 11.20 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 11.21 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 11.22 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 11.23 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 11.24 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 11.25 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 11.26 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 11.27 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 11.28 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 11.29 + * POSSIBILITY OF SUCH DAMAGE. 11.30 + * 11.31 + */ 11.32 package de.uapcore.lightpit.entities; 11.33 11.34 import java.util.Objects;
12.1 --- a/src/main/java/de/uapcore/lightpit/entities/VersionStatus.java Sun May 10 10:58:31 2020 +0200 12.2 +++ b/src/main/java/de/uapcore/lightpit/entities/VersionStatus.java Mon May 11 19:09:06 2020 +0200 12.3 @@ -1,3 +1,31 @@ 12.4 +/* 12.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 12.6 + * 12.7 + * Copyright 2018 Mike Becker. All rights reserved. 12.8 + * 12.9 + * Redistribution and use in source and binary forms, with or without 12.10 + * modification, are permitted provided that the following conditions are met: 12.11 + * 12.12 + * 1. Redistributions of source code must retain the above copyright 12.13 + * notice, this list of conditions and the following disclaimer. 12.14 + * 12.15 + * 2. Redistributions in binary form must reproduce the above copyright 12.16 + * notice, this list of conditions and the following disclaimer in the 12.17 + * documentation and/or other materials provided with the distribution. 12.18 + * 12.19 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 12.20 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 12.21 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 12.22 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 12.23 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 12.24 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 12.25 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 12.26 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 12.27 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 12.28 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 12.29 + * POSSIBILITY OF SUCH DAMAGE. 12.30 + * 12.31 + */ 12.32 package de.uapcore.lightpit.entities; 12.33 12.34 public enum VersionStatus {