src/main/java/de/uapcore/lightpit/AbstractLightPITServlet.java

changeset 167
3f30adba1c63
parent 163
a5b9632729b6
child 168
1c3694ae224c
equal deleted inserted replaced
166:6eede6088d41 167:3f30adba1c63
26 * POSSIBILITY OF SUCH DAMAGE. 26 * POSSIBILITY OF SUCH DAMAGE.
27 * 27 *
28 */ 28 */
29 package de.uapcore.lightpit; 29 package de.uapcore.lightpit;
30 30
31 import de.uapcore.lightpit.dao.DaoProvider; 31 import de.uapcore.lightpit.dao.DataAccessObject;
32 import de.uapcore.lightpit.dao.postgres.PGDaoProvider; 32 import de.uapcore.lightpit.dao.PostgresDataAccessObject;
33 import org.slf4j.Logger; 33 import org.slf4j.Logger;
34 import org.slf4j.LoggerFactory; 34 import org.slf4j.LoggerFactory;
35 35
36 import javax.servlet.ServletException; 36 import javax.servlet.ServletException;
37 import javax.servlet.http.HttpServlet; 37 import javax.servlet.http.HttpServlet;
54 54
55 private static final Logger LOG = LoggerFactory.getLogger(AbstractLightPITServlet.class); 55 private static final Logger LOG = LoggerFactory.getLogger(AbstractLightPITServlet.class);
56 56
57 private static final String SITE_JSP = jspPath("site"); 57 private static final String SITE_JSP = jspPath("site");
58 58
59
60 @FunctionalInterface
61 protected interface SQLFindFunction<K, T> {
62 T apply(K key) throws SQLException;
63
64 default <V> SQLFindFunction<V, T> compose(Function<? super V, ? extends K> before) throws SQLException {
65 Objects.requireNonNull(before);
66 return (v) -> this.apply(before.apply(v));
67 }
68
69 default <V> SQLFindFunction<K, V> andThen(Function<? super T, ? extends V> after) throws SQLException {
70 Objects.requireNonNull(after);
71 return (t) -> after.apply(this.apply(t));
72 }
73
74 static <K> Function<K, K> identity() {
75 return (t) -> t;
76 }
77 }
78
79 /** 59 /**
80 * Invocation mapping gathered from the {@link RequestMapping} annotations. 60 * Invocation mapping gathered from the {@link RequestMapping} annotations.
81 * <p> 61 * <p>
82 * Paths in this map must always start with a leading slash, although 62 * Paths in this map must always start with a leading slash, although
83 * the specification in the annotation must not start with a leading slash. 63 * the specification in the annotation must not start with a leading slash.
99 * Creates a set of data access objects for the specified connection. 79 * Creates a set of data access objects for the specified connection.
100 * 80 *
101 * @param connection the SQL connection 81 * @param connection the SQL connection
102 * @return a set of data access objects 82 * @return a set of data access objects
103 */ 83 */
104 private DaoProvider createDataAccessObjects(Connection connection) throws SQLException { 84 private DataAccessObject createDataAccessObjects(Connection connection) {
105 final var df = (DataSourceProvider) getServletContext().getAttribute(DataSourceProvider.Companion.getSC_ATTR_NAME()); 85 final var df = (DataSourceProvider) getServletContext().getAttribute(DataSourceProvider.Companion.getSC_ATTR_NAME());
106 if (df.getDialect() == DataSourceProvider.Dialect.Postgres) { 86 if (df.getDialect() == DataSourceProvider.Dialect.Postgres) {
107 return new PGDaoProvider(connection); 87 return new PostgresDataAccessObject(connection);
108 } 88 }
109 throw new UnsupportedOperationException("Non-exhaustive if-else - this is a bug."); 89 throw new UnsupportedOperationException("Non-exhaustive if-else - this is a bug.");
110 } 90 }
111 91
112 private void invokeMapping(Map.Entry<PathPattern, Method> mapping, HttpServletRequest req, HttpServletResponse resp, DaoProvider dao) throws IOException { 92 private void invokeMapping(Map.Entry<PathPattern, Method> mapping, HttpServletRequest req, HttpServletResponse resp, DataAccessObject dao) throws IOException {
113 final var pathPattern = mapping.getKey(); 93 final var pathPattern = mapping.getKey();
114 final var method = mapping.getValue(); 94 final var method = mapping.getValue();
115 try { 95 try {
116 LOG.trace("invoke {}#{}", method.getDeclaringClass().getName(), method.getName()); 96 LOG.trace("invoke {}#{}", method.getDeclaringClass().getName(), method.getName());
117 final var paramTypes = method.getParameterTypes(); 97 final var paramTypes = method.getParameterTypes();
120 if (paramTypes[i].isAssignableFrom(HttpServletRequest.class)) { 100 if (paramTypes[i].isAssignableFrom(HttpServletRequest.class)) {
121 paramValues[i] = req; 101 paramValues[i] = req;
122 } else if (paramTypes[i].isAssignableFrom(HttpServletResponse.class)) { 102 } else if (paramTypes[i].isAssignableFrom(HttpServletResponse.class)) {
123 paramValues[i] = resp; 103 paramValues[i] = resp;
124 } 104 }
125 if (paramTypes[i].isAssignableFrom(DaoProvider.class)) { 105 if (paramTypes[i].isAssignableFrom(DataAccessObject.class)) {
126 paramValues[i] = dao; 106 paramValues[i] = dao;
127 } 107 }
128 if (paramTypes[i].isAssignableFrom(PathParameters.class)) { 108 if (paramTypes[i].isAssignableFrom(PathParameters.class)) {
129 paramValues[i] = pathPattern.obtainPathParameters(sanitizeRequestPath(req)); 109 paramValues[i] = pathPattern.obtainPathParameters(sanitizeRequestPath(req));
130 } 110 }
177 } 157 }
178 158
179 boolean paramsInjectible = true; 159 boolean paramsInjectible = true;
180 for (var param : method.getParameterTypes()) { 160 for (var param : method.getParameterTypes()) {
181 paramsInjectible &= HttpServletRequest.class.isAssignableFrom(param) 161 paramsInjectible &= HttpServletRequest.class.isAssignableFrom(param)
182 || HttpServletResponse.class.isAssignableFrom(param) 162 || HttpServletResponse.class.isAssignableFrom(param)
183 || PathParameters.class.isAssignableFrom(param) 163 || PathParameters.class.isAssignableFrom(param)
184 || DaoProvider.class.isAssignableFrom(param); 164 || DataAccessObject.class.isAssignableFrom(param);
185 } 165 }
186 if (paramsInjectible) { 166 if (paramsInjectible) {
187 try { 167 try {
188 PathPattern pathPattern = new PathPattern(mapping.get().requestPath()); 168 PathPattern pathPattern = new PathPattern(mapping.get().requestPath());
189 169
358 * @param <T> the type of the request parameter 338 * @param <T> the type of the request parameter
359 * @param <R> the type of the looked up entity 339 * @param <R> the type of the looked up entity
360 * @return the retrieved entity or an empty optional if there is no such entity or the request parameter was missing 340 * @return the retrieved entity or an empty optional if there is no such entity or the request parameter was missing
361 * @throws SQLException if the find function throws an exception 341 * @throws SQLException if the find function throws an exception
362 */ 342 */
363 protected <T, R> Optional<R> findByParameter(HttpServletRequest req, Class<T> clazz, String name, SQLFindFunction<? super T, ? extends R> find) throws SQLException { 343 protected <T, R> Optional<R> findByParameter(HttpServletRequest req, Class<T> clazz, String name, Function<? super T, ? extends R> find) {
364 final var param = getParameter(req, clazz, name); 344 final var param = getParameter(req, clazz, name);
365 if (param.isPresent()) { 345 if (param.isPresent()) {
366 return Optional.ofNullable(find.apply(param.get())); 346 return Optional.ofNullable(find.apply(param.get()));
367 } else { 347 } else {
368 return Optional.empty(); 348 return Optional.empty();

mercurial